剑指 Offer II 040. 矩阵中最大的矩形(单调栈)


题目

给定一个由 0 和 1 组成的矩阵 matrix ,找出只包含 1 的最大矩形,并返回其面积。

注意:此题 matrix 输入格式为一维 01 字符串数组。

示例 1:
在这里插入图片描述

输入:matrix = [“10100”,“10111”,“11111”,“10010”]
输出:6
解释:最大矩形如上图所示。

示例 2:

输入:matrix = []
输出:0

示例 3:

输入:matrix = [“0”]
输出:0

示例 4:

输入:matrix = [“1”]
输出:1

示例 5:

输入:matrix = [“00”]
输出:0

提示:

rows == matrix.length
cols == matrix[0].length
0 <= row, cols <= 200
matrix[i][j] 为 ‘0’ 或 ‘1’

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/PLYXKQ


一、解题思路

我们首先计算出矩阵的每个元素的上边连续 1 的数量,使用二维数组 up 记录,其中 up[i][j] 为矩阵第 i 行第 j 列元素的上边连续 1 的数量。
如图:
在这里插入图片描述
这样就转化成了计算up数组每一行的最大矩形面积,最后比较每行的最大矩形面积得到最终答案。
最大矩形面积解题思路请看:
剑指 Offer II 039. 直方图最大矩形面积(单调栈)<必看>

也可转化成left数组,每个元素的左边连续 1 的数量,使用二维数组 left 记录,其中 left[i][j] 为矩阵第 i 行第 j 列元素的左边连续 1 的数量。

二、代码

class Solution {
    //针对列,遍历每个i的高度,寻找低于其高度的边界
    //相当于offer 039 的高度图逆时针转90度
    public int maximalRectangle(String[] matrix) {
        int n = matrix.length;
        if(n==0) return 0;
        int m = matrix[0].length();
        //left数组表示当前left[i][j]左边有几个连续1
        int[][] left = new int[n][m];

        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(matrix[i].charAt(j)=='1')
                    left[i][j]= j==0? 1:left[i][j-1]+1;
            }
        }
        int res =0;
        for(int j=0;j<m;j++){
            //当前列left的上下边界
            int[] up =new int[n];
            int[] down=new int[n];
            Arrays.fill(down,n);
            //单调栈 存放下标
            Deque<Integer> eq = new LinkedList<>();
            for(int i=0;i<n;i++){
                //根据入栈出栈时机确定边界,所以每列中的每个数都会入栈
                //所以首先明确出栈条件
                while(!eq.isEmpty()&&left[eq.peek()][j]>=left[i][j]) down[eq.pop()]=i;
                //入栈时,也就是栈空或者left[eq.peek()][j] < left[i][j] 那么eq.peek()就是i的上边界
                up[i]= eq.isEmpty() ? -1:eq.peek();

                eq.push(i);
            }
            for(int i=0;i<n;i++){
                res=Math.max(res,(down[i]-up[i]-1)*left[i][j]);
            }
        }
        return res;
    }
    //正向的
    // public int maximalRectangle(String[] matrix) {
    //     int n = matrix.length;
    //     if(n==0) return 0;
    //     int m = matrix[0].length();
    //     int[][] up  = new int[n][m];
    //     for(int i=0;i<n;i++){
    //         for(int j=0;j<m;j++){
    //             if(matrix[i].charAt(j)=='1')
    //                 up[i][j] = i==0? 1:up[i-1][j]+1;
    //         }
    //     }
    //     int res =0;
    //     for(int i=0;i<n;i++){
    //         //当前行的左右边界
    //         int[] left=new int[m];
    //         int[] right = new int[m];
    //         Arrays.fill(right,m);
    //         Deque<Integer> eq= new LinkedList<>();
    //         for(int j=0;j<m;j++){
    //             //出栈条件
    //             while(!eq.isEmpty()&&up[i][eq.peek()]>=up[i][j]) right[eq.pop()]=j;
    //             left[j] = eq.isEmpty() ? -1:eq.peek();
    //             eq.push(j);
    //         }
    //         for(int j=0;j<m;j++){
    //             res= Math.max(res,(right[j]-left[j]-1)*up[i][j]);
    //         }
    //     }
    //     return res;
    // }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值