【leetcode每日刷题】85. Maximal Rectangle

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/m0_38103546/article/details/102572958

Given a 2D binary matrix filled with 0's and 1's, find the largest rectangle containing only 1's and return its area.

Example:

Input:
[
  ["1","0","1","0","0"],
  ["1","0","1","1","1"],
  ["1","1","1","1","1"],
  ["1","0","0","1","0"]
]
Output: 6
import java.util.Stack;

class num85 {
    public int maximalRectangle(char[][] matrix) {
        int m = matrix.length;
        if(m == 0) return 0;
        int n = matrix[0].length;
        int max = 0;
        int[] height = new int[n+1];
        height[n] = 0;
        for(int i=0; i<m; i++){
            for(int j=0; j<n; j++){
                if(matrix[i][j] == '1'){
                    height[j] += 1;
                }else{
                    height[j] = 0;
                }
            }
            max = Math.max(max, largestRectangleArea(height));
        }
        return max;
    }
    // 使用局部峰值的方法
    // public int largestRectangleArea(int[] height){
    //     int res = 0;
    //     for(int i=0; i<height.length; i++){
    //         if(i+1<height.length && height[i]<=height[i+1]) continue;
    //         int minH = height[i];
    //         for(int j=i; j>=0; j--){
    //             minH = Math.min(minH, height[j]);
    //             int temp = (i-j+1) * minH;
    //             res = Math.max(temp, res);
    //         }
    //     }
    //     return res;
    // }
    // 使用堆栈的方法
    public int largestRectangleArea(int[] height){
        int res = 0;
        Stack<Integer> stack = new Stack<Integer>();
        for(int i=0; i<height.length; ++i){
            if(stack.empty() || height[stack.peek()] < height[i]){
                stack.push(i);
            }else{
                int cur = stack.pop();
                res = Math.max(res, height[cur] * (stack.empty()? i: i-stack.peek()-1));
                --i;
            }

        }
        return res;
    }
    public int largestRectangleArea(int[] height){
        int res = 0;
        Stack<Integer> stack = new Stack<Integer>();
        for(int i=0; i<height.length; ++i){
            while(!stack.empty()&&height[stack.peek()]>=height[i]){
                int cur = stack.pop();
                res = Math.max(res, height[cur] * (stack.empty()? i: i-stack.peek()-1));
            }
            stack.push(i);
        }
        return res;
    }
    public static void main(String[] args) {
        char[][] matrix = {
            {'1','0','1','0','0'},
            {'1','0','1','1','1'},
            {'1','1','1','1','1'},
            {'1','0','0','1','0'}
          };
        num85 solution = new num85();
        System.out.println(solution.maximalRectangle(matrix));
    }
}

将该问题看做求直方图的最大面积的问题的变形形式,将每层都看做直方图的底层,然后求当前可表示成的直方图的最大矩形面积。

1、求以每层为底层的直方图高度

遍历该层的每一个元素,如果为0则将高度置为0,否则为上一层的高度加1

2、求直方图的最大矩形面积

(1)使用局部峰值的方法;首先找到局部峰值,然后根据峰值计算当前的最大面积。因为面积的值局限于直方图最矮的高度,如果有递增的直方图序列,不需要冗余计算峰值前面的面积,因为包括峰值的后面的矩形肯定大于前面的矩形面积。

eg:[2, 1, 5, 6, 2, 3]

对于1,5,6这样的递增序列,不需要重复计算[2, 1, 5]中的最大值,因为加上6之后的最大矩形肯定更大。

但是此种方法超时。

(2)使用堆栈的方法;此种方法使用堆栈维护一个局部的峰值,将递增的序列放入堆栈中,遇到小于当前的高度后就开始进行处理,处理的时候每次弹出一个栈中的宽度为1的最高元素进行计算,然后再弹出宽度为2的矮一些的元素进行计算,直到栈顶的元素的高度值小于当前i值。堆栈中存放高度的索引值。

stack: 0[2]  遇到1小于2,开始计算,得到最大值为2; 将栈中的元素弹出。

stack:1[1] , 2[5], 3[6], 遇到2小于6,开始求最大值,得出最大值为10,将栈中的2,3弹出。

stack: 1[1], 4[2] , 5[3], 开始求最大值,得出最大值为4。

猜你喜欢

转载自blog.csdn.net/m0_38103546/article/details/102572958