Zuoshen Advanced Advanced Class 3 (Usage of TreeMap sequence table to record linear data, use of sliding window, prefix and record structure, discarding of possibilities)

Table of contents

【Case 1】

[Title description]

[Analysis of ideas]

【Code】

【Case 2】

[Title description]

[Analysis of ideas]

【Code】

【Case 3】

[Title description]

[Analysis of ideas]

【Code】

【Case 4】

[Title description]

 [Analysis of ideas]

【Code】


【Case 1】

[Title description]

[Analysis of ideas]

There is overlap between the buildings here, and then let's describe the outline array, so we need to know the maximum height of each point. Because the height of the middle part of each building is equal, we only need to know which building is the tallest at this point, and because the height of the middle part of the building is equal, we only care about the starting and ending positions of each building. We can construct an array like this through matrix [the array stores nodes, and the nodes include three information: position, lifting situation, and height]. The array is sorted by position and lifting situation. (1) Sort by position first, in ascending order ( 2) If the two positions are the same, the starting position (in the case of rising) is ranked first.

Through such a sequence array, we can construct a sequence table of height and appearance. If it rises, a record will be added. If it falls, a record will be deleted. If the record is 0, it will be deleted. Through this sequence table, we can know the maximum height of the current position (the relationship between the position and the maximum height is also constructed as a sequence table to store, so that when generating the contour, the contour position changes are orderly). We can know through the change in height The contour changes, and then the contour array is constructed from the sequence table of position and maximum height.

【Code】

package AdvancedPromotion3;

import java.util.*;

/**
 * @ProjectName: study3
 * @FileName: Ex1
 * @author:HWJ
 * @Data: 2023/9/18 10:27
 */
public class Ex1 {
    public static void main(String[] args) {
        int[][] matrix = {
   
   {2, 5, 6}, {1, 7, 4}, {4, 6, 7}, {3, 6, 5}, {10, 13, 2}, {9, 11, 3}, {12, 14, 4}, {10, 12, 5}};
        List<List<Integer>> ans = getContourMatrix(matrix);
        for (List<Integer> integers : ans) {
            for (int i : integers) {
                System.out.print(i + " ");
            }
            System.out.println();
        }

    }

    public static class Node {
        int x;
        boolean isAdd; // true 表示当前为一个楼的开始, false表示当前地点为一个楼的结束
        int height;

        public Node(int x, boolean isAdd, int height) {
            this.x = x;
            this.isAdd = isAdd;
            this.height = height;
        }


    }

    public static class NodeComparator implements Comparator<Node> {

        @Override
        public int compare(Node o1, Node o2) {
            if (o1.x != o2.x) {
                return o1.x - o2.x;
            }
            if (o1.isAdd != o2.isAdd) {
                return o1.isAdd ? -1 : 1;
            }
            return 0;
        }
    }

    public static List<List<Integer>> getContourMatrix(int[][] matrix) {
        Node[] nodes = new Node[matrix.length * 2];
        for (int i = 0; i < matrix.length; i++) {
            nodes[i * 2] = new Node(matrix[i][0], true, matrix[i][2]);
            nodes[i * 2 + 1] = new Node(matrix[i][1], false, matrix[i][2]);
        }
        Arrays.sort(nodes, new NodeComparator());
        TreeMap<Integer, Integer> heightAndNums = new TreeMap<>();
        TreeMap<Integer, Integer> maxHeight = new TreeMap<>();
        for (Node node : nodes) {
            if (node.isAdd) {
                if (!heightAndNums.containsKey(node.height)) { //如果不存在就新建记录
                    heightAndNums.put(node.height, 1);
                } else {
                    heightAndNums.put(node.height, heightAndNums.get(node.height) + 1);
                }
            } else {
                if (heightAndNums.get(node.height) == 1) { // 如果只剩一条记录了就直接删除
                    heightAndNums.remove(node.height);
                } else {
                    heightAndNums.put(node.height, heightAndNums.get(node.height) - 1);
                }
            }
            if (heightAndNums.isEmpty()) { // 这里通过顺序表记录当前结点的最大高度
                maxHeight.put(node.x, 0);
            } else {
                maxHeight.put(node.x, heightAndNums.lastKey());
            }
        }
        int preHeight = 0;
        int start = 0;
        List<List<Integer>> res = new ArrayList<>();
        for (int x : maxHeight.keySet()) {
            int curHeight = maxHeight.get(x);
            if (preHeight != curHeight) { // 如果高度发生了变化,就构建轮廓
                if (preHeight != 0) { // 如果之前的高度为0, 说明之前的那个地方到现在的地方没有楼
                    res.add(new ArrayList<>(Arrays.asList(start, x, preHeight)));
                }
                preHeight = curHeight;
                start = x;
            }
        }

        return res;
    }
}

【Case 2】

[Title description]

[Analysis of ideas]

Solve it with a sliding window. If the sum of the elements of the current window is greater than k, l++, less than k, r++, if ==k, record the answer, and r++.

Because it is a positive array, the sliding window can maintain monotonicity during the movement process. Make sure the answers are correct.

【Code】

package AdvancedPromotion3;

/**
 * @ProjectName: study3
 * @FileName: Ex2
 * @author:HWJ
 * @Data: 2023/9/18 11:07
 */
public class Ex2 {
    public static void main(String[] args) {
        int[] arr = {1,2,3,1,1,1,2,1,1,3};
        System.out.println(getMaxLen(arr, 3));
    }

    public static int getMaxLen(int[] arr, int k){
        int l = 0;
        int r = 0;
        int sum = 0;
        int res = -1;
        while (r < arr.length){
            if (sum == k){
                res = Math.max(r - l + 1, res);
                r++;
                if (r == arr.length){
                    break;
                }
                sum += arr[r];
            }
            if (sum > k){
                sum -= arr[l++];
            }
            if (sum < k){
                r++;
                if (r == arr.length){
                    break;
                }
                sum += arr[r];
            }
        }
        return res;
    }
}

【Case 3】

[Title description]

Given an unordered array arr, the elements can be positive, negative, or 0, and an integer k is given. Find the length of the longest subarray whose cumulative sum is equal to k among all subarrays of arr.

[Analysis of ideas]

Build a hash table, put the prefix sum into it and reach the index position of this prefix sum. Add k = 5.

The hash table has a record 12,i. Indicates 0--i, the sum of all the elements is 12, if there is a prefix sum in the traversal that is 17, and all are j (j > i), then the cumulative sum of i+1 --- j should be k. Just record the answer.

【Code】

package AdvancedPromotion3;

import java.util.HashMap;

/**
 * @ProjectName: study3
 * @FileName: Ex3
 * @author:HWJ
 * @Data: 2023/9/18 11:17
 */
public class Ex3 {
    public static void main(String[] args) {

    }

    public static int getMaxLen(int[] arr, int k){
        if (arr.length == 0){
            return 0;
        }
        HashMap<Integer, Integer> sumIndex = new HashMap<>();
        sumIndex.put(0, -1);
        int res = -1;
        int sum = 0;
        for (int i = 0; i < arr.length; i++) {
            sum += arr[i];
            if (sumIndex.containsKey(sum - k)){
                res = Math.max(res, i - sumIndex.get(sum - k));
            }
            sumIndex.put(sum, i);
        }
        return res;
    }
}

  

【Case 4】

[Title description]

 [Analysis of ideas]

Construct two array representations. One array minSum[i] represents the farthest place that can be reached starting from i, and minimizes the sum of this sub-array; minIndex[i] represents the index of the farthest place that can be reached starting from i.

For example: the first row of the table represents the unordered array arr, the second row represents minSum, and the third row represents minIndex.

3 -2 -4 0 6
-3 -6 -4 0 6
3 3 3 3 4

After getting this, it is equivalent to dividing an array into several parts, and then we can find the beginning of the next part through minIndex. We only consider whether we can add the next part next time.

For example

We started traversing at position 0, added three parts, and reached position k, but he could not join the next part, so we started traversing from 1 to see if he could join the next part . We default to 1-k being legal, because if it is illegal, it must not be added to the next part, so its effective size must be less than 0-k. We need to find the maximum effective length, so it must not be a valid solution, so we directly default He is legal. Only if he can join the next area, we will consider him as a possible answer. This can discard many invalid possibilities and reduce the complexity of the algorithm.

【Code】

package AdvancedPromotion3;

/**
 * @ProjectName: study3
 * @FileName: Ex4
 * @author:HWJ
 * @Data: 2023/9/18 12:10
 */
public class Ex4 {
    public static void main(String[] args) {
        int[] arr = {3,-2,-4,0,6};
        System.out.println(getMaxLen(arr, -2));
    }

    public static int getMaxLen(int[] arr, int k){
        int n = arr.length;
        int[] minSub = new int[n];
        int[] minIndex = new int[n];
        minSub[n - 1] = arr[n - 1];
        minIndex[n - 1] = arr[n - 1];
        for (int i = n - 2; i >= 0; i--) {
            if (minSub[i + 1] <= 0){
                minSub[i] = arr[i] + minSub[i + 1];
                minIndex[i] = minIndex[i + 1];
            }else {
                minSub[i] = arr[i];
                minIndex[i] = i;
            }
        }
        int res = 0;
        int p = 0;
        int sum = 0;
        boolean loop =true; // 使第一次进入求解答案时,能正确进入循环
        for (int i = 0; i < n; i++) {
           while (p < n && (loop || sum <= k)){ // 这里不初始化p 和 sum,这样可以舍弃大量不是最优解的解。
               res = Math.max(res, p - i);
               sum += minSub[p];
               p = minIndex[p] + 1;
               loop = false;
           }
           sum -= arr[i];
        }
        return res;
    }
}

 

Guess you like

Origin blog.csdn.net/weixin_73936404/article/details/132962564