Recursive Solution for Maximum Matrix Sequences and Problems

Previously, my colleague asked an algorithm question that requires a little bit of brainstorming. I think it's interesting. The idea may give you some inspiration, so I'll record it here.

subject

There is an existing n-order matrix with only 0,1 elements, which maximizes the sum of sequences of consecutive adjacent (horizontal or vertical, no rings) elements with a value of 1.Assume the following matrix

Then the sequence of elements with successive adjacent values of 1 of this matrix is 4,3, respectively (as shown), and the maximum sum of the sequences that meet the criteria of this matrix is 4.

Solving problems

To calculate the maximum of a sequence sum, we can first find all possible sequences, and naturally find the maximum of the sequence sum. How do we find these sequences?First, we find that the starting point and ending point of each sequence must be 1. We can traverse every element of the matrix. If the element value is 1, we can start looking for all sequences starting from this element. We know that a sequence can extend vertically and horizontally, so we can start with this element and find its top and bottom or left.Elements with a value of 1, then starting with those found, continue to look for elements with a value of 1 in the top, bottom, left and right of the element, and so on (recursion). If no qualified value is found, the sequence terminates. During the traversal process, each qualified sequence is saved, and the maximum value of the sequence sum is obtained.

The text is a bit ambiguous, so let's take a closer look at how to find the maximum sequence and

1. All elements with a value of 1 are traversed from left to right, from top to bottom. The first eligible element is in the upper right corner, so the sequence is searched from this element.

2. With this element as the starting point, look for the element with a value of 1 from top to bottom, and find that only the element below this element meets the criteria.

3. Looking for an element with a value of 1 from the start, you can see that the element on the top has a value of 1, and the element on the left obviously meets the criteria. The element on the top does not meet the criteria because it is the element that is currently traversed in the traversal sequence (what happens if the above element meets the criteria?The sequence in which the element is the starting point has returned to the first step and falls into an infinite loop, so the element with the next value of 1 cannot be the element in the sequence currently being traversed!, which is the key to solving the problem and must be noted!) So the qualified elements at this point are shown in the following red circle

4. If you look for an element that has a top, bottom, and both sides of the element, you can see that both sides of the element are 1. According to the analysis of the previous step, the right element is the element that has been traversed in the current traversal sequence, so it does not meet the criteria, then only the left and the bottom elements are eligible.

  1. Look again for the elements with 1 from top to bottom, and the qualified element is the red box element in step 3. Because this element is the element that has been traversed in the current traversal sequence, it does not meet the criteria. The traversal of the sequence ends here, so we know that the maximum value of the sequence sum starting from the upper right element is 4, and the traversed elements are connected.Elements, as shown

or

6. Similarly, follow the steps above to iterate through the remaining elements with a value of 1. The maximum values of the sequence sum starting with these elements are 4, 3, 3, and 4, respectively (as shown below).

7. To sum up, the maximum sum of sequences of elements with successive adjacent values of 1 for this matrix is 4.

code implementation

Okay, now let's see how the code works. First, we'll use a data structure to represent the matrix. Obviously, it's a good idea to represent the matrix as an array. Here we use a one-dimensional array to represent the matrix. The Java code is as follows

public class Matrix {
    /**
     * @param matrix  matrix
     * @param dimension Represents a dimension-order matrix
     * @return Maximum value of matrix sequence
     */
    private static Integer getMaxSequetialSum(int[] matrix, int dimension) {
        int count = matrix.length;      // Number of elements of a matrix
        int maxSequentialSum = 0;       // Maximum value of matrix sequence
        // Traverse elements one by one
        for (int index = 0; index < count; index++) {
            int elementValue = matrix[index];
            // If the current element is 1, then start with this element and find the maximum value of the sum of sequences starting with this element
            if (elementValue == 1) {
                // Record the position of elements traversed by the sequence starting with the element marked index
                Set<Integer> traverseElementSet = new HashSet<>();
                traverseElementSet.add(index);
                // The following elements with index as the starting point are the maximum values of the sequence
                int currentSequetialSum = getCurrentVerticeSequetialSum(matrix, traverseElementSet, index, dimension);
                maxSequentialSum = Math.max(maxSequentialSum, currentSequetialSum);
            }
        }
        return maxSequentialSum;
    }

    /**
     * @param matrix  matrix
     * @param traverseElementSet Location of traversed elements in the sequence
     * @param index     Position of element, starting point of sequence
     * @param dimension dimension Order Matrix
     * @return Maximum value of a sequence starting with an element whose position is index
     */
    private static Integer getCurrentVerticeSequetialSum(int[] matrix, Set<Integer> traverseElementSet, int index, int dimension) {
        // Find the position of left and right elements above and below elements that are index in the matrix
        int left = index - 1;
        int right = index + 1;
        int up = index - dimension;
        int down = index + dimension;

        // Maximum value of a sequence starting with the left element
        int leftIndexSum = 0;

        // Maximum value of a sequence starting with the right element
        int rightIndexSum = 0;

        // Maximum value of the sequence starting with the above elements
        int upIndexSum = 0;

        // The maximum value of a sequence starting with the following elements
        int downIndexSum = 0;

        /**
         * The following four if else s are designed to check the validity of each element's location and must have a value of 1
         * It is important to note that elements cannot be elements that the sequence has traversed!
         * If the upper, lower, and left elements are not legal, the sequence terminates, dotting the elements of the traversed sequence and
         */

        if (left >= 0 && matrix[left] == 1 && !traverseElementSet.contains(left)) {
            Set<Integer> leftTraverseElementSet = new HashSet<>(traverseElementSet);
            leftTraverseElementSet.add(left);
            leftIndexSum = getCurrentVerticeSequetialSum(matrix, leftTraverseElementSet, left, dimension);
        } else {
            leftIndexSum = traverseElementSet.size();
        }

        // The right element must be on the same line as the element in index
        if (right / dimension == index / dimension && matrix[right] == 1 && !traverseElementSet.contains(right)) {
            traverseElementSet.add(right);
            Set<Integer> rightTraverseElementSet = new HashSet<>(traverseElementSet);
            rightTraverseElementSet.add(right);
            rightIndexSum = getCurrentVerticeSequetialSum(matrix, rightTraverseElementSet, right, dimension);
        } else {
            rightIndexSum = traverseElementSet.size();
        }

        if (up >= 0 && matrix[up] == 1 && !traverseElementSet.contains(up)) {
            Set<Integer> upTraverseElementSet = new HashSet<>(traverseElementSet);
            upTraverseElementSet.add(up);
            upIndexSum = getCurrentVerticeSequetialSum(matrix, upTraverseElementSet, up, dimension);
        } else {
            upIndexSum = traverseElementSet.size();
        }

        if (down < matrix.length && matrix[down] == 1 && !traverseElementSet.contains(down)) {
            Set<Integer> downTraverseElementSet = new HashSet<>(traverseElementSet);
            downTraverseElementSet.add(down);
            downIndexSum = getCurrentVerticeSequetialSum(matrix, downTraverseElementSet, down, dimension);
        } else {
            downIndexSum = traverseElementSet.size();
        }

        // Find the maximum value of a sequence extending up, down, left, right, and right from an element with an index of position
        return Collections.max(Arrays.asList(leftIndexSum, rightIndexSum, upIndexSum, downIndexSum));
    }

    public static void main(String[] args) {
        // Initialize the matrix, assuming it is a 5 x 5 matrix
        int[] matrix1 = {
                0,0,0,0,1,
                0,0,1,1,1,
                0,0,0,1,0,
                0,0,0,0,0,
        };
        int max = Matrix.getMaxSequetialSum(matrix1, 5);
        System.out.println(max);  // Print 4

        int[] matrix2 = {
                0,0,0,0,1,
                0,0,1,1,1,
                0,0,1,1,0,
                0,0,0,0,0,
        };
        max = Matrix.getMaxSequetialSum(matrix2, 5);
        System.out.println(max);  // Print 6
    }
}

Time Complexity and Spatial Complexity Analysis

Any algorithm, if you don't talk about time and space complexity, is a rogue. Next, let's look at the time and space complexity of the above solutions.First, let's look at spatial complexity. Because we used traverseElementSet to record the locations of traversed sequence elements during traversal, the spatial complexity is obviously O(n). This topic uses recursion, time complexity is really complex, and it's not intuitive enough to test the programmer's level. So let's see how to deduce it. We use f(n) to represent locations as nFrom the above deduction, it is natural to know that f(n) is also known as long as the maximum sum of sequences starting from the upper, lower and left elements of this element is calculated.That is, the sequence and number of times starting at position n are converted to the number of times the sequence sum starting at the top, bottom and left elements of this element is calculated

F(n) = f (left) + F (right) + F (up) + F (down)

Consider carefully that the sequence sum of the four elements above and below can be considered to be the same number of times. If f(n) = 4f( left) assumes that the number of matrix elements is N, f(n) = 4N has N elements, so the total time complexity is O (4N<sup>2</sup>), that is, O (n<sup>2</sup>). If you have a better time complexity solution, you are welcome to discuss it together!

summary

At first glance, this problem does not have any clue, and it is not as easy to see how to solve it by using recursive thinking as by inverting binary trees. We need to be patient with the analysis and learn to break down the problem. The breakdown ideas are as follows: how to get the maximum value of a continuous sequence into how to find all the sequences --> The element from which the sequence starts must be 1 --> how to find a value of 1All sequences starting with elements of the --> As long as all sequences starting with elements with left and right values of 1 above and below this element are found and --> Then elements with left and right values of 1 above and below are recursively searched for all sequences starting with elements with their respective left and right values of 1 --> After all sequences are found, the maximum sequence is found naturally.

Reproduced from Public Number: Number Sea

Tags: Java

Posted on Mon, 13 Jan 2020 11:44:02 -0500 by xionfoo