啊这个,我之前面试的时候倒是做了一个最大正方形,一下就做出来了的。现在这个思考一下感觉和“lc042接雨水”有点像。在那道题里面用到了暴力算法和单调栈,这道题里也是。在做这道题之前,我先做了一下lc84最大矩形,因为那个题里的思路能够很好地用到本题上面。简而言之,我们扫描每一行,用类似前缀和的思想记录下每个位置到当前为止连续1的个数,对于每一行,我们再将这一行看作底,去求若干以该行为底的柱形中所包含的最大矩形有多大。将上述计算用在每一行中找到最终的答案。
后续发现用“哨兵”避免分类讨论时没必要用俩,只要用一个就行并且要将stack里的初始元素设为-1即指向新加入的末尾哨兵。这样在遍历时就没必要从1开始而是自然地从0开始即可。
这个算法的时间复杂度是O(NM),空间复杂度是O(N)。
python:
class Solution1:
def maximalRectangle(self, matrix: List[List[str]]) -> int:
m = len(matrix)
if m == 0:
return 0
n = len(matrix[0])
heights = [0] * n
ans = 0
for i in range(m):
for j in range(n):
if matrix[i][j] == "0":
heights[j] = 0
else:
heights[j] += 1
ans = max(ans, self.largestRectangleArea(heights))
return ans
def largestRectangleArea(self, heights) -> int:
heights = [0] + heights + [0]
size = len(heights)
stack = [0]
res = 0
for i in range(1, size):
while heights[i] < heights[stack[-1]]:
cur_height = heights[stack.pop()]
cur_width = i - stack[-1] - 1
res = max(res, cur_height * cur_width)
stack.append(i)
return res
class Solution2:
def maximalRectangle(self, matrix: List[List[str]]) -> int:
m = len(matrix)
if m == 0:
return 0
n = len(matrix[0])
heights = [0] * n
ans = 0
for i in range(m):
for j in range(n):
if matrix[i][j] == "0":
heights[j] = 0
else:
heights[j] += 1
ans = max(ans, self.largestRectangleArea(heights))
return ans
def largestRectangleArea(self, heights) -> int:
heights = heights + [0]
size = len(heights)
stack = [-1]
res = 0
for i in range(size):
while heights[i] < heights[stack[-1]]:
cur_height = heights[stack.pop()]
cur_width = i - stack[-1] - 1
res = max(res, cur_height * cur_width)
stack.append(i)
return res
PREVIOUSlc084.柱状图中的最大矩形
NEXTlc172.阶乘后的零