题目

给定一个仅包含0和1的二维二进制矩阵,找出只包含1的最大矩形,并返回其面积。
image.png

解答

以行进行切分,height[j]表示在目前的底(第1行)的j位置往上(包括j位置),有多少个连续的1。
对于每一次切割,都利用更新后的height数组来求出以当前行为底的情况下,最大的矩形是什么。那么这么多次切割中,最大的那个矩形就是我们要的答案。

问题转化成:每次切分后,如何求最大矩形的面积?

image.png
● 第1根高度为3的柱子向左无法扩展,它的右边是2,比3小,所以向右也无法扩展,则以第1根柱子为高度的矩形面积就是31==3;
● 第2根高度为2的柱子向左可以扩1个距离,因为它的左边是3,比2大;右边的柱子也是3,所以向右也可以扩1个距离,则以第2根柱子为高度的矩形面积就是2
3==6;
● 第3根高度为3的柱子向左没法扩展,向右也没法扩展,则以第3根柱子为高度的矩形面积就是31==3;
● 第4根高度为0的柱子向左没法扩展,向右也没法扩展,则以第4根柱子为高度的矩形面积就是0
1==0;

因此,对于当前柱子为高度形成的矩阵的面积,要找到距离距离该柱子 左右距离最近,且它高度小的位置(短板决定不能继续扩张了)。
这个过程怎么计算快呢?单调栈
**

代码

  1. class Solution:
  2. def maximalRectangle(self, matrix: List[List[str]]) -> int:
  3. if matrix is None or len(matrix) == 0 or len(matrix[0]) == 0:
  4. return 0
  5. maxArea = 0
  6. height = [0] * len(matrix[0])
  7. for i in range(len(matrix)):
  8. for j in range(len(matrix[0])):
  9. height[j] = height[j] + 1 if matrix[i][j] == '1' else 0
  10. print(height)
  11. maxArea = max(maxArea, self.maxRecFromBottom(height))
  12. return maxArea
  13. def maxRecFromBottom(self, height):
  14. if not any(height):
  15. # 全是0
  16. return 0
  17. stack = []
  18. maxArea = 0
  19. for i in range(len(height)):
  20. while stack and height[i] <= height[stack[-1]]:
  21. j = stack.pop()
  22. k = stack[-1] if stack else -1
  23. curArea = (i - k - 1) * height[j]
  24. maxArea = max(maxArea, curArea)
  25. stack.append(i)
  26. while stack:
  27. j = stack.pop()
  28. k = stack[-1] if stack else -1
  29. curArea = (len(height) - k - 1) * height[j]
  30. maxArea = max(maxArea, curArea)
  31. return maxArea