leetcode (栈->hard)42,84,85,1703

  进入hard模式后感觉从努力解题变成了努力看懂大佬思路。。。。

 

42  这个看了下思路大概是找到数组中最大的那个值,然后首尾两个指针往最大值遍历,当前值小于当前值之前的最大值的差值就是当前点能蓄水的多少。

  不过找到一个大佬的思路,感觉太强了,就是同时遍历首尾,动态计算首尾最大值,一次遍历即可。传送门-> https://blog.csdn.net/zhangdx001/article/details/105455728

 leetcode (栈->hard)42,84,85,1703

 

 

    public static int trap(int[] height) {
        int left = 0,right = height.length-1;
        int leftMax =0,rightMax = 0,score = 0;
        while (left <= right){
            if (height[left] < height[right]){
                if (height[left] <leftMax ){
                    score+=leftMax-height[left];
                }else {
                    leftMax = height[left];
                }
                left++;
            }else {
                if (height[right] < rightMax ){
                    score+=rightMax-height[right];
                }else {
                    rightMax = height[right];
                }
                right--;
            }
        }
        return score;
    }

 

84  这个题自己有想出来了暴力解法,不过可能由于过于暴力(N^2的复杂度)。导致如下结果

leetcode (栈->hard)42,84,85,1703

 

 

   leetcode (栈->hard)42,84,85,1703

 

   原题如下

leetcode (栈->hard)42,84,85,1703

 

 

   感觉这个题的点就是在于遍历这个数组的时候,如何能够避免重复的运算。也就是说遍历的时候每个点都需要找到其左边最大的面积,遍历的时机根据大佬的思路就是当前点小于上一个点的时候。此时上一个点就可以开始计算面积了,并且计算区间就是直到小于当前遍历点的时候,由于可能出现例如(2,2,3,4,2)最后一个点与前面最小点相等的情况,此时计算区间根据前面的逻辑就只会计算(3,4) ,此时三个2就不会参与运算,所以根据大佬的思路就是在数组前后自己手动加个0  ,那么这个数字就变成了(0,2,2,3,4,2,0),那么此时遍历到2时会计算(3,4),而遍历到最后的0的时候就会计算(2,2,2),具体的代码如下

    public int largestRectangleArea(int[] heights) {
  int[] tps = new int[heights.length+2];
        System.arraycopy(heights,0,tps,1,heights.length);
        LinkedList<Integer> list = new LinkedList<>();
        int max = 0;
        for (int i = 0; i < tps.length; i++) {
                while (!list.isEmpty() && tps[i] < tps[list.peek()]){
                    Integer pop = list.pop();
                    max = Math.max(max,(i-list.peek()-1)*tps[pop]);
                }

            list.push(i);
        }

        return max;
    }

 

85 看着原本感觉以为很复杂的题居然没有依靠大佬思路一遍就做出来通过了而且时间还挺快 (喜极而泣)

  我的思路是构造一个dp数组记录每个点左边的最长的1的长度,然后再顺序计算该点往上的点能构造的最大矩形

 

  leetcode (栈->hard)42,84,85,1703

 

 leetcode (栈->hard)42,84,85,1703

 

 

    public static int maximalRectangle(char[][] matrix) {
        if (matrix.length == 0) return 0;
        int[][] dp = new int[matrix.length][matrix[0].length];
        int max = 0;
        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix[i].length; j++) {
                if ( i == 0 && j == 0){
                    max = dp[0][0] =  matrix[0][0] == '1'?1:0;
                }else {
                    char k = matrix[i][j];
                    if (k == '0'){
                        dp[i][j] = 0;
                    }else {
                        dp[i][j] = j == 0 ?1:dp[i][j-1] +1;
                        int t = i, s = 0,tpMin = dp[i][j];
                        while (t >= 0 && dp[t][j] >0 ){
                            s++;
                            tpMin = Math.min(tpMin,dp[t][j]);
                            max = Math.max(max,s*tpMin);
                            t--;
                        }
                    }
                }
            }
        }
        return max;

    }

 

1703

  虽然标签给的栈不过这个题,我的理解是找到包含0最少的K个1子序列,然后找到其所有值向中位数移动后的步数即可(奇偶数要分情况),应该是使用滑动窗口来做,不过思路有了代码写不出来。尴尬。。先放着吧(先耻辱结束栈系列。。)

leetcode (栈->hard)42,84,85,1703

 

上一篇:E2. Close Tuples (hard version) 组合数+逆元


下一篇:【题解】「NOI2019」机器人 [*hard]