题目描述

 
Problem: 剑指 Offer II 040. 矩阵中最大的矩形
文章目录
- 题目描述
- 解法一:暴力解法
- 思路
- 解题方法
- 复杂度
- Code
 
- 解法二:单调栈解法
解法一:暴力解法
思路
首先, 按行获取到达某一元素位置时,之前与当前连续1的个数,这个连续1的个数就会作为所求矩阵的备选宽度。然后, 再迭代遍历,以列不变的基础上,向上改变行的位置,将原始位置与改变位置之差作为目标矩阵的备选长度,最后求得最大矩阵面积。
解题方法
计算矩阵宽度时,先以当前位置连续1的个数作为宽度,在后续更新时,因为要保证这个矩阵范围内都可以被囊括,就以迭代遍历中的最小宽度作为矩阵宽度。
计算矩阵面积时,用宽度乘以当前遍历到的行数之差,找出和已有结果对比的最大值,作为最大面积。
复杂度
- 时间复杂度:
O ( m 2 n ) O(m^2n) O(m2n)
其中 m 和 n 分别是矩阵的行数和列数。计算 left 矩阵需要 O ( m n ) O(mn) O(mn)的时间。随后对于矩阵的每个点,需要 O(m) 的时间枚举高度。故总的时间复杂度为 O ( m n ) + O ( m n ) ⋅ O ( m ) = O ( m 2 n ) O(mn)+O(mn)⋅O(m)=O(m^2n) O(mn)+O(mn)⋅O(m)=O(m2n)。
- 空间复杂度:
O ( m n ) O(mn) O(mn)
其中 m 和 n 分别是矩阵的行数和列数。我们分配了一个与给定矩阵等大的数组,用于存储每个元素的左边连续 1 的数量。
Code
C++
class Solution {
public:
    int maximalRectangle(vector<string>& matrix) {
        int m = matrix.size();
        if(m == 0)                  return 0;
        int n = matrix[0].size();
        vector<vector<int>> left(m, vector<int>(n, 0));
        for(int i = 0; i < m; i++) {                                    // 记录每行中连续1的个数
            for(int j = 0; j < n; j++) {
                if(matrix[i][j] == '1') {
                    left[i][j] = (j == 0 ? 0 : left[i][j - 1]) + 1;
                }
            }
        }
        int res = 0;
        for(int i = 0; i < m; i++) {
            for(int j = 0; j < n; j++) {
                if(matrix[i][j] == '0') {                           // 遇到0说明不是矩阵,则直接跳出
                    continue;
                }
                int width = left[i][j];                             
                int area = width;                                   // 此时的面积是以长度=1,宽度=left[i][j],得到的面积
                for(int k = i - 1; k >= 0; k--) {                   // 因为之前记录的是每行连续的1(也就是长度),因此这里需要变化的是的整体的行长(宽度),从i-1开始
                    width = min(width, left[k][j]);                 // 找到当前范围内的最小宽度,遍历每种范围内的情况
                    area = max(area, (i - k + 1) * width);          // 获取当列不变时,行从0~i之间的最大面积
                }
                res = max(res, area);                               // 找到整体的最大面积
            }
        }
        return res;
    }
};
Python
class Solution:
    def maximalRectangle(self, matrix: List[str]) -> int:
        m = len(matrix)
        if m == 0:
            return 0
        n = len(matrix[0])
        left = [[0 for _ in range(n)] for _ in range(m)]        
        res = 0
        for i in range(m):
            for j in range(n):
                if matrix[i][j] == '1':
                    left[i][j] = left[i][j - 1] + 1 if j != 0 else 1
        for i in range(m):
            for j in range(n):
                width, area = left[i][j], left[i][j]
                for k in range(i - 1, -1, -1):
                    width = min(width, left[k][j])
                    area = max(area, (i - k + 1) * width)
                res = max(res, area)    
        return res
参考文章:矩阵中最大的矩形


















