相似题目:
【LeetCode】84. 柱状图中最大的矩形(单调栈).

1. 题目描述:

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

示例:

输入:
[
[“1”,“0”,“1”,“0”,“0”],
[“1”,“0”,“1”,“1”,“1”],
[“1”,“1”,“1”,“1”,“1”],
[“1”,“0”,“0”,“1”,“0”]
]
输出: 6

2. 解题思路

2.1 法一、单调栈

具体可参考【LeetCode】84. 柱状图中最大的矩形(单调栈) 这一题目,代码都相似

class Solution:
    def maximalRectangle(self, matrix: List[List[str]]) -> int:
        if not matrix:
            return 0
        # 单调栈的应用 2
        def getLargestRectLayer(heights):
            ret = 0
            stack = []
            heights = [0] + heights + [0]
            for i in range(len(heights)):
                while stack and heights[stack[-1]] > heights[i]:
                    tmp = stack.pop()
                    ret = max(ret, (i - stack[-1] - 1) * heights[tmp])
                stack.append(i)
            return ret
        def getHeights(array, heights):
            for i in range(len(heights)):
                if array[i] == "1":
                    heights[i] += 1
                else:
                    heights[i]  = 0
            return heights
        # 对于每一层 获取heights数组即可
        ret = 0
        m = len(matrix)
        for i in range(m):
            if i == 0:
                heights = list(map(int, matrix[0]))
            else:
                heights = getHeights(matrix[i], heights)
            retLayer = getLargestRectLayer(heights)
            ret = max(ret, retLayer)
        return ret

2.2 法二、动态规划

面试的时候用的是动态规划,当时面试官就问说能不能用栈来解题

class Solution:
    def maximalRectangle(self, matrix: List[List[str]]) -> int:
        maxarea = 0

        dp = [[0] * len(matrix[0]) for _ in range(len(matrix))]
        for i in range(len(matrix)):
            for j in range(len(matrix[0])):
                if matrix[i][j] == '0': continue

                # compute the maximum width and update dp with it
                width = dp[i][j] = dp[i][j-1] + 1 if j else 1

                # compute the maximum area rectangle with a lower right corner at [i, j]
                for k in range(i, -1, -1):
                    width = min(width, dp[k][j])
                    maxarea = max(maxarea, width * (i-k+1))
        return maxarea

复杂度分析

  1. 时间复杂度 : O ( N 2 M ) O(N^2M) O(N2M) 。由于需要遍历同一列中的值,计算每个点对应最大面积需要 O ( N ) O(N) O(N)。对全部 N ∗ M N * M NM个点都要计算,因此总共 O ( N ) ∗ O ( N M ) = O ( N 2 M ) O(N) * O(NM) = O(N^2M) O(N)O(NM)=O(N2M).

  2. 空间复杂度 : O ( N M ) O(NM) O(NM)。我们分配了一个等大的数组,用于存储每个点的最大宽度。

参考

  1. LeetCode官方题解(动态规划).
  2. LeetCode题解(单调栈).