题面
原题链接
给定一个仅包含 0 和 1 的二维二进制矩阵,找出只包含 1 的最大矩形,并返回其面积。
解析
本题如果直接采用暴力枚举的解法,时间复杂度为
O
(
n
6
)
\mathcal{O}(n^6)
O(n6),考虑枚举下边界加预处理进行时间复杂度优化.
枚举第
i
i
i行,设第
i
i
i行第
j
j
j列的向上连续的1的个数为
f
(
i
,
j
)
f(i, j)
f(i,j),则
f
(
i
,
j
)
=
{
0
,
m
a
t
r
i
x
(
i
,
j
)
=
0
1
+
f
(
i
−
1
,
j
)
,
m
a
t
r
i
x
(
i
,
j
)
=
1
f(i, j)= \begin{cases} 0, matrix(i, j)=0\\ 1+f(i-1, j), matrix(i, j)=1 \end{cases}
f(i,j)={0,matrix(i,j)=01+f(i−1,j),matrix(i,j)=1
然后问题可以转化为Leetcode 84.柱状图中最大矩形求解.
AC代码
class Solution {
private:
int largestRectangleArea(vector<int>& heights) {
int n = heights.size();
vector<int> left(n), right(n);
stack<int> st; // 存储下标的单调栈
// left->right sweep
for(int i=0; i<n; ++i){
while(!st.empty() && heights[st.top()]>=heights[i]) st.pop();
if(st.empty()) left[i]=-1;
else left[i]=st.top();
st.push(i);
}
st = stack<int>();
// right->left sweep
for(int i=n-1; ~i; --i){
while(!st.empty() && heights[st.top()]>=heights[i]) st.pop();
if(st.empty()) right[i]=n;
else right[i]=st.top();
st.push(i);
}
int ans=0;
for(int i=0; i<n; ++i){
ans=max(ans, heights[i]*(right[i]-left[i]-1));
// cout<<heights[i]<<" "<<left[i]<<" "<<right[i]<<endl;
}
return ans;
}
public:
int maximalRectangle(vector<vector<char>>& matrix) {
if(matrix.empty() || matrix[0].empty()) return 0;
int n = matrix.size(), m=matrix[0].size();
vector<vector<int>> f(n, vector<int>(m)); // 上方有多少个连续的1
for(int i=0; i<n; ++i)
for(int j=0; j<m; ++j){
if(matrix[i][j]=='1' && i) f[i][j]=1+f[i-1][j];
else if(matrix[i][j]=='1') f[i][j]=1;
else f[i][j]=0;
}
int ans = 0;
for(int i=0; i<n; ++i) ans=max(ans, largestRectangleArea(f[i])); // 枚举下边界
return ans;
}
};