📜  QA – 安置测验|排列组合|问题 4(1)

📅  最后修改于: 2023-12-03 15:34:33.721000             🧑  作者: Mango

QA – 安置测验|排列组合|问题 4

题目描述

给定一个由数字 0 和 1 组成的矩阵,找出其中最大的全 1 子矩阵。

示例:

输入:

[ ["1","0","1","0","0"], ["1","0","1","1","1"], ["1","1","1","1","1"], ["1","0","0","1","0"] ]

输出: 6

思路解析

此题可以使用动态规划的思想来解决,定义一个一维数组 heights 来存储每一行的以该行为底的连续 1 的个数。

例如:

[
     ["1","0","1","0","0"],
     ["1","0","1","1","1"],
     ["1","1","1","1","1"],
     ["1","0","0","1","0"]
]

可以得到一个 heights 数组为:

[1, 0, 1, 0, 0]
[2, 0, 2, 1, 1]
[3, 1, 3, 2, 2]
[4, 0, 0, 3, 0]

每一行都看成一个直方图,然后根据每一列迭代计算,可以得到一个函数 maxArea(heights) 来计算以该列为底的最大矩形面积。

使用求解最大面积的方法遍历每一列,得到最大子矩阵的面积即可。

代码实现
class Solution:
    def maximalRectangle(self, matrix: List[List[str]]) -> int:
        if not matrix:
            return 0
        
        m, n = len(matrix), len(matrix[0])
        heights = [0] * n
        res = 0
        
        for i in range(m):
            for j in range(n):
                heights[j] = heights[j] + 1 if matrix[i][j] == '1' else 0
                
            res = max(res, self.maxArea(heights))
        
        return res
        
    def maxArea(self, heights: List[int]) -> int:
        if not heights:
            return 0
        
        n = len(heights)
        left, right = [0] * n, [0] * n
        left[0], right[-1] = -1, n
        
        for i in range(1, n):
            tmp = i - 1
            while tmp >= 0 and heights[tmp] >= heights[i]:
                tmp = left[tmp]
            left[i] = tmp
                
        for i in range(n - 2, -1, -1):
            tmp = i + 1
            while tmp < n and heights[tmp] >= heights[i]:
                tmp = right[tmp]
            right[i] = tmp
        
        res = 0
        for i in range(n):
            res = max(res, (right[i] - left[i] - 1) * heights[i])
        
        return res
复杂度分析

时间复杂度:O(MN)

空间复杂度:O(N)

其中 M 和 N 分别为输入矩阵的行和列数。