题目描述
给定一个仅包含 0 和 1 的二维二进制矩阵,找出只包含 1
的最大矩形,并返回其面积。
样例
输入:
[
["1","0","1","0","0"],
["1","0","1","1","1"],
["1","1","1","1","1"],
["1","0","0","1","0"]
]
输出: 6
算法
(单调栈) $O(nm)$
- 将 Largest Rectangle in Histogram 问题扩展到二维。
- 一行一行考虑,类比 Largest Rectangle in Histogram,一行内所有柱形条的高度
heights
就是当前(i, j)
位置能往上延伸的最大高度。 - 直接套用 Largest Rectangle in Histogram 的单调栈算法即可。
时间复杂度
- 枚举每一行的时间复杂度是 $O(n)$,行内单调栈的时间复杂度是 $O(m)$,故总时间复杂度为 $O(nm)。
空间复杂度
- 需要额外 $O(m)$ 的空间存放高度和用于单调栈。
C++ 代码
class Solution {
public:
int maximalRectangle(vector<vector<char>>& matrix) {
int n = matrix.size(), m, ans = 0;
if (n == 0)
return 0;
m = matrix[0].size();
vector<int> heights(m + 1, 0);
heights[m] = -1;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++)
if (matrix[i][j] == '0')
heights[j] = 0;
else
heights[j]++;
stack<int> st;
for (int j = 0; j <= m; j++) {
while (!st.empty() && heights[j] < heights[st.top()]) {
int cur = st.top();
st.pop();
if (st.empty())
ans = max(ans, heights[cur] * j);
else
ans = max(ans, heights[cur] * (j - st.top() - 1));
}
st.push(j);
}
}
return ans;
}
};
wzcdl%%%%%%%%%%%%
为什么在if(matrix[i][j] == ‘0’)要重置height为0 呢?
因为此处能向上的最大高度是 0 了呀
6666666666666666
设定vector为m+1的思路是什么呢…
在最后加一个哨兵位置,方便处理。
老哥,如果是求最大正方形,该咋处理
可以考虑动态规划,$f(i, j)$ 表示以 $(i, j)$ 为右下角的最大正方形,转移时, 如果 $matrix(i, j) = 1$,$f(i, j) = \min( f(i - 1, j), f(i, j - 1), f(i - 1, j -1) ) + 1$;否则 $f(i, j) = 0$。最后扫描 $f$ 数组找最大值。
那初始化f[0][0]=1 哇?为啥是min不是max哇。
初始化全是0,取min是因为扩展一格需要那三个地方同时满足
现在我才明白老哥当时说的话。。。
补充一下大佬的话,$f(i,j)$表示$(i,j)$为右下角的最大正方形的边长