【队列&栈】LeetCode 85. 最大矩形【困难】

给定一个仅包含 0 和 1 、大小为 rows * cols 的二维二进制矩阵,找出只包含 1 的最大矩形,并返回其面积。

示例 1:

 

输入:matrix = [["1","0","1","0","0"],["1","0","1","1","1"],["1","1","1","1","1"],["1","0","0","1","0"]]
输出:6
解释:最大矩形如上图所示。
示例 2:

输入:matrix = []
输出:0
示例 3:

输入:matrix = [["0"]]
输出:0
示例 4:

输入:matrix = [["1"]]
输出:1
示例 5:

输入:matrix = [["0","0"]]
输出:0
 

提示:

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

 

【分析:前缀和+单调栈】

参数定义:

m, n:矩阵行列数目。

pre:长度为n+1,初始值为0的数组,记录每个位置上方(包含当前位置)连续1的个数,最后一个位置为0,便于单调栈处理(不好理解的话参考下面绿色字体部分的详解即可)。

stack:单调栈,存储元素的索引,且索引对应的元素单调递增。

思路:

 

利用“前缀和”的思想求连续1的个数:

1. 对于pre的计算,当前位置j为0,则pre[j] = 0;当前位置为1,则需要加上上一层连续1的个数,即pre[j] += 1.

2. 如第二行(下标从0开始)pre[2] = [3,1,1,2,2,0],最后多一个0出来,是为了便于单调栈处理。

单调栈计算最大矩形:

1. 初始化栈,存入下标-1,便于处理所有元素弹出栈后的情况。

2. 当栈顶索引index对应的元素pre[index]大于当前索引为k的元素num时,将栈顶元素index弹出,因为栈中索引对应的值是单调递增的,所以此时栈顶元素stack[-1]到k-1之间的数均是不小于pre[index]的,此时以pre[index]为高的矩阵长度为k-stack[-1]-1,面积S=pre[index]*(k-stack[-1]-1)。

3. pre数组末尾添加0的目的,就是能将所有元素弹出栈,从而计算所有矩阵的面积。

4. 利用res记录最大矩阵面积。

时间复杂度:O(mn)

空间复杂度:O(n)

class Solution:
    def maximalRectangle(self, matrix: List[List[str]]) -> int:
        if not matrix:
            return 0
        raws, cols = len(matrix), len(matrix[0])

        # 记录当前位置上方连续“1”的个数
        pre = [0] * (cols + 1) # pre:长度为n+1,初始值为0的数组,记录每个位置上方(包括当前位置)连续1的个数,最后一个位置为0,便于单调栈处理。
        area = 0 # 初始化最大矩形面积
        for raw in range(raws):
            for col in range(cols):
                # 前缀和
                pre[col] = pre[col] + 1 if matrix[raw][col] == "1" else 0
            
            # 单调栈
            stack = [-1] # 初始化栈,存入下标-1,便于处理所有元素弹出栈后的情况
            for cur_index, cur_num in enumerate(pre):
                while stack and pre[stack[-1]] > cur_num:
                    top_index = stack.pop()
                    area = max(area, pre[top_index] * (cur_index - stack[-1] - 1))
                stack.append(cur_index)
        return area

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2022-05-04 20:16  Ariel_一只猫的旅行  阅读(45)  评论(0编辑  收藏  举报