leetcode最大矩形_LeetCode85.最大矩形(Maximal Rectangle)

85. 最大矩形

给定一个仅包含 0 和 1 、大小为 rows x 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.lengthcols == matrix.length0 <= row, cols <= 200matrix[i][j] 为 '0' 或 '1'

来源:力扣(LeetCode)

链接:https://leetcode-cn.com/problems/maximal-rectangle/

Link:https://leetcode.com/problems/maximal-rectangle/

动态规划 + 栈

O(M * N)

上一题, 有了一种计算最大长方形的办法, 那么一行行扫描, 从当前一行往上记录1的个数, 计算每个直方图中的最大矩形面积

# 第一排|    1    0    1    0    0--------------------------------    [1,   0,   1,   0,   0]# 第二排|    1    0    1    0    0|    1    0    1    1    1--------------------------------    [2,   0,   2,   1,   1]# 第三排|    1    0    1    0    0|    1    0    1    1    1|    1    1    1    1    1--------------------------------    [3,   1,   3,   2,   2]# 第四排|    1    0    1    0    0|    1    0    1    1    1|    1    1    1    1    1|    1    0    0    1    0--------------------------------    [4,   0,   0,   3,   0]

递推公式

if matrix[row][j] == '1':  dp[j] = matrix[row][j] + dp[j]else:  dp[j] = 0

计算方向

由上到下

边界条件

class Solution:    def maximalRectangle(self, matrix: List[List[str]]) -> int:        if len(matrix) == 0 or len(matrix[0]) == 0:            return 0        row = len(matrix)        col = len(matrix[0])        res = 0        dp = [0 for i in range(col)]        for i in range(row):            for j in range(col):                if matrix[i][j] == '1':                    dp[j] += 1                else:                    dp[j] = 0            res = max(res, self.calculateArea(dp))        return res    def calculateArea(self, nums: List[int]) -> int:        heights = nums + [-1]        stack = []        res = 0        for i in range(len(heights)):            while stack and heights[stack[-1]] > heights[i]:                index = stack.pop()                left = stack[-1] if stack else -1                area = (i - left - 1) * heights[index]                res = max(res, area)            stack.append(i)        return res

动态规划 + 三个数组

考虑切割的话, n个数有n + 1个分割点, 逐行扫描, 找到(右边界 - 左边界) * (高),就可以计算面积

    |  1  |  0  |  1  |  0  |  0  |    |  1  |  0  |  1  |  1  |  1  |    |  1  |  1  |  1  |  1  |  1  |    |  1  |  0  |  0  |  1  |  0  |    ^     ^     ^     ^     ^     ^    0th   1th   2th   3th   4th   5th    其中, M * N = 4 * 5

状态定义

边界用切割点来表示, 从第ith高度出发,能够组成的最大面积

计算公式

以下dp更新都是考虑到上一行, 上一行作为等号的右值dp[j], 当前行作为等号的左值dp[j]

左边界, 计算时考虑上一行

left_bound = 0如果matrix[i][j] == 1, left[j] = max(left[j], left_bound)相反,左边界向右移动, left_bound = j + 1, 高度0的左边界重置为0

右边界,计算时考虑上一行

right_bound = N如果matrix[i][j] == 1, right[j] = min(right[j], right_bound)相反,有边界向左移动, right_bound = j, 高度0的右边界重置为N

高度,计算时考虑上一行

如果matrix[i][j] == 1, height[j] += 1相反 height[j] = 0

初始化

left, height数组初始化为0

right数组初始化为N

边界条件

当元素为0时, left, height重置为0

当元素为0时, right重置为N

计算方向

逐行扫描

代码如下:

class Solution:    def maximalRectangle(self, matrix: List[List[str]]) -> int:        if len(matrix) == 0 or len(matrix[0]) == 0:            return 0        m = len(matrix)        n = len(matrix[0])        height = [0 for i in range(n)]        left = [0 for i in range(n)]        right = [n for i in range(n)]        res = 0        for i in range(m):            # 高度            for j in range(n):                if matrix[i][j] == '1':                    height[j] += 1                else:                    height[j] = 0            # 左边界            left_boundry = 0            for j in range(n):                if matrix[i][j] == '1':                    left[j] = max(left[j], left_boundry)                else:                    # left[j] = 0                    left_boundry = j + 1            # 右边界            right_boundry = n            for j in range(n)[::-1]:                if matrix[i][j] == '1':                    right[j] = min(right[j], right_boundry)                else:                    # right[j] = n                    right_boundry = j            # 面积            for j in range(n):                res = max(res, (right[j] - left[j]) * height[j])        return res

--End--

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值