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--