Leetcode 85.最大矩形


题目描述:

给定一个仅包含 01 、大小为 rows x cols 的二维二进制矩阵,找出只包含 1 的最大矩形,并返回其面积。

示例 1:

1
2
3
输入:matrix = [["1","0","1","0","0"],["1","0","1","1","1"],["1","1","1","1","1"],["1","0","0","1","0"]]
输出:6
解释:最大矩形如上图所示。

示例 2:

1
2
输入:matrix = []
输出:0

示例 3:

1
2
输入:matrix = [["0"]]
输出:0

示例 4:

1
2
输入:matrix = [["1"]]
输出:1

示例 5:

1
2
输入:matrix = [["0","0"]]
输出:0

提示:

  • rows == matrix.length
  • cols == matrix[0].length
  • 0 <= row, cols <= 200
  • matrix[i][j]'0''1'

链接:

https://leetcode-cn.com/problems/maximal-rectangle


题目分析

  做这道题之前先看看与之关联的上一道题 Leetcode 84.柱状图中最大的矩形。我们可以发现,如果我们按照每一列的顺序维护 heights,就可以复用上一题的代码。就像下面这样。这样是可以遍历所有可能存在的矩形的,因此得到的答案就是最终答案。
leetcode85.png
  PS:下面的代码中 largestRectangleArea 函数来自上一题,使用的是单调栈的做法,具体过程可以参阅上一题题解。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class Solution {
int largestRectangleArea(vector<int>& heights) {
int result = 0;
stack<pair<int, int>> s;
s.push({-1, 0});
heights.push_back(0);

for(int i = 0; i < heights.size(); i++){
while(heights[i] < s.top().second){
int height = s.top().second;
s.pop();
result = max(result, (i - s.top().first - 1) * height);
}
s.push({i, heights[i]});
}
return result;
}
public:
int maximalRectangle(vector<vector<char>>& matrix) {
if(matrix.size() == 0) return 0;
int maxArea = 0;
vector<int> heights(matrix[0].size(), 0);
for(int i = 0; i < matrix.size(); i++){
for(int j = 0; j < matrix[0].size(); j++){
if(matrix[i][j] == '1'){
heights[j]++;
}
else heights[j] = 0;
}
maxArea = max(maxArea, largestRectangleArea(heights));
}
return maxArea;
}
};

  时间复杂度:$O(mn)$,其中 $m、n$ 分别是矩阵的行数和列数。我们遍历矩阵的一行进行一次处理,而处理的函数时间复杂度是 $O(n)$。因此总的时间复杂度就是 $O(mn)$。
  空间复杂度:$O(n)$,其中 $n$ 是矩阵的列数。因为我们需要维护一个 heights 数组,大小为 $O(n)$,并且进行处理的 largestRectangleArea 函数也需要 $O(n)$ 的栈空间。