【leetcode每日刷题】85. Maximal Rectangle

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。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值