题目:
给定一个仅包含 0 和 1 的二维二进制矩阵,找出只包含 1 的最大矩形,并返回其面积。
示例:
输入:
[
[“1”,“0”,“1”,“0”,“0”],
[“1”,“0”,“1”,“1”,“1”],
[“1”,“1”,“1”,“1”,“1”],
[“1”,“0”,“0”,“1”,“0”]
]
输出: 6
思路1:
如下图,可以当作84题,求出每一层的高度,然后计算每一层的最大矩形面积。
图片引用自85题windliang的题解:图片出处链接
思路2:动态规划。
对矩阵中的每一个位置,我们先找出以该位置为底的最大的高,然后用这个高尽可能向左向右延伸,得到左右边界就可以算出矩阵的面积。
我们需要维护的数据结构有:该位置的高height
,以这个高度左右最大可以延伸的位置left
和right
,这三个数据结构的更新均依赖于上一层。
- 高的更新:
height[j] = height[j] + 1 if matrix[i][j] == "1" else 0
即,如果当前位置是1
,那么当前高度就在上一层的高度上加一;否则就是0
-
left
的更新:
首先我们可以计算当前位置左边距离最近的0
的位置l
,然后和上一层这个位置的left
相比,二者取较大的:
left[j] = max(left[j], l)
-
right
的更新:
我们可以计算当前位置右边距离最近的0
的位置r
,然后和上一层这个位置的right
相比,二者取较小的:
right[j] = min(right[j], r)
三个值都有了就可以进行矩阵面积的更新。
代码:
class Solution(object):
def maximalRectangle(self, matrix):
"""
:type matrix: List[List[str]]
:rtype: int
"""
if not matrix:
return 0
l = len(matrix[0])
height = [0] * l
left = [-1] * l
right = [l] * l
maxArea = 0
for i in range(len(matrix)):
for j in range(l):
height[j] = height[j] + 1 if matrix[i][j] == "1" else 0
if height[j] == 0:
left[j] = -1
right[j] = l
else:
temp = j
while temp >= 0 and matrix[i][temp] == "1":
temp -= 1
left[j] = max(left[j], temp)
temp = j
while temp < l and matrix[i][temp] == "1":
temp += 1
right[j] = min(right[j], temp)
maxArea = max(maxArea, height[j] * (right[j] - left[j] - 1))
return maxArea
上面代码可以简单优化一下,更新left
和right
的时候,不用每一个点都重新搜索,可以像单调栈一样一次遍历就更新。
优化代码:
class Solution(object):
def maximalRectangle(self, matrix):
"""
:type matrix: List[List[str]]
:rtype: int
"""
if not matrix:
return 0
l = len(matrix[0])
height = [0] * l
left = [-1] * l
right = [l] * l
maxArea = 0
for i in range(len(matrix)):
cur_left = -1
cur_right = l
for j in range(l):
height[j] = height[j] + 1 if matrix[i][j] == "1" else 0
if matrix[i][j] == "1":
left[j] = max(left[j], cur_left)
else:
left[j] = -1
cur_left = j
for j in range(l-1, -1, -1):
if matrix[i][j] == "1":
right[j] = min(right[j], cur_right)
else:
right[j] = l
cur_right = j
for j in range(l):
maxArea = max(maxArea, height[j] * (right[j] - left[j] - 1))
return maxArea