zoukankan      html  css  js  c++  java
  • [leetcode] 85. 最大矩形

    85. 最大矩形

    解法1:

    一个思路就是这个可以看作84. 柱状图中最大的矩形的扩展,这道题的二维矩阵每一层向上都可以看做一个直方图,输入矩阵有多少行,就可以形成多少个直方图,对每个直方图都调用 84. 柱状图中最大的矩形 中的方法,就可以得到最大的矩形面积。

    class Solution {
        public int maximalRectangle(char[][] matrix) {
            int m = matrix.length;
            if (m == 0) return 0;
            int n = matrix[0].length;
            if (n == 0) return 0;
    
            int[] height = new int[n];
            int ans = 0;
    
            for (int i = 0; i < m; i++) {
                for (int j = 0; j < n; j++) {
                    if (matrix[i][j] == '0') height[j] = 0;
                    else if (matrix[i][j] == '1') height[j] += 1;
                }
                ans = Math.max(largestRectangleArea(height), ans);
            }
            return ans;
        }
    
        public int largestRectangleArea(int[] heights) {
            if (heights.length == 0) return 0;
            Stack<Integer> stack = new Stack<>();
    
            int max = 0;
            for (int i = 0; i < heights.length; i++) {
                while (!stack.isEmpty() && heights[stack.peek()] >= heights[i]) {
                    int tmp = stack.pop();
                    // 把当前的tmp木板作为最短木板,看能组成的最大面积是多少
                    max = Math.max(max, heights[tmp] * (stack.empty() ? i : i - stack.peek() - 1));
                }
                stack.push(i);
            }
    
            int tmp = 0;
            int len = heights.length;
            while (!stack.isEmpty()) {
                tmp = stack.pop();
                max = Math.max(max, heights[tmp] * (stack.empty() ? len : len - stack.peek() - 1));
            }
    
            return max;
        }
    }
    

    解法2:

    另外一个思路就是,想办法如何很方便的表示出一个矩形。比如说,对于以(i,j)点为右下角的矩形。

    大家可以先想暴力思路,实际上大部分的优化思路,都是以暴力思路基础而来的。
    暴力思路:枚举(i,j)为一个矩形的右下角,然后以(i,j)为起点,向左、向上看,能组成的最大矩形是什么。时间复杂度为O(n^4)。
    仔细观察一下,其实在向左、向上看,能组成的最大矩形是什么这个过程中,是存在重复计算的。也就是说当我们算完点(i,j)后,(i+1,j)点,我们或许只需要看第i+1行就可以了。

    所以,我们可否用动态规划来做呢?

    有个思路很巧妙:
    height数组和上面一样,height表示高,这里的left数组表示左边界是1的位置,right数组表示右边界是1的位置,那么对于任意一行的第j个位置,矩形为(right[j] - left[j]) * height[j]

    具体参考:算法学习之动态规划 85. Maximal Rectangle

    文章里讲的方法我大概是懂了,其核心思路是从第一行开始一行一行地处理,然后其left与right数组巧妙的保存了上层的状态,使得其能表示出矩阵左边界或者右边界的位置,进而就很方便的表示出了一个矩形了

    但是,我觉得我是想不出来这个思路的- -。。非常的巧妙啊

  • 相关阅读:
    Linux网络协议栈(三)——网络设备(1)
    Linux网络协议栈(三)——网络设备(2)
    Linux网络协议栈(四)——链路层(1)
    Linux网络协议栈(四)——链路层(2)
    监视系统中进程的创建和终止
    APIHOOK
    APIHOOK
    Try running RemoteDll as Administrator
    用注册表创建无法删除的IE快捷方式
    用注册表创建无法删除的IE快捷方式
  • 原文地址:https://www.cnblogs.com/acbingo/p/9398981.html
Copyright © 2011-2022 走看看