解法一:依次以矩阵中每个元素为左上角计算局部最大矩阵,其中最大的就是最终结果。这种解法计算以一个点为左上角的局部最大矩阵时务必想办法最优化,否则就会超时,这里的解决办法是以该点为起点,行优先逐渐增加列的方式来计算局部最大矩阵,当局部矩阵不能再增大时及时停止。
class Solution {
public:
int maximalRectangle(vector<vector<char> > &matrix) {
int m=matrix.size();
if(m==0)
{
return 0;
}
int n=matrix[0].size();
if(n==0)
{
return 0;
}
int max=0;
for(int i=0;i<m;++i)
{
for(int j=0;j<n;++j)
{
//calc max rectangle which uses i,j as the left upper corner
int tmp=0;
int pre=0;
int acc=0;
int l=i;
while((l<m)&&(matrix[l][j]!='0'))
{
<span style="white-space:pre"> </span>int k=j;
while((k<n)&&(matrix[l][k]!='0'))
{
k++;
}
acc=k-j;
if(pre==0)
{
pre=acc;
}
else
{
pre=pre>acc?acc:pre;
}
if(pre*(l-i+1)>tmp)
{
tmp=pre*(l-i+1);
}
l++;
}
//
//cout<<"("<<i<<","<<j<<")="<<tmp<<endl;
if(tmp>max)
{
max=tmp;
}
}
}
return max;
}
};
解法2:预处理,将以每个元素为起点的最长可以达到的行长度记录下来,这样在计算局部最大矩形时可以少一层嵌套的循环,在Leetcode上提高了近4倍的执行效率
class Solution {
public:
int maximalRectangle(vector<vector<char> > &matrix) {
int m=matrix.size();
if(m==0)
{
return 0;
}
int n=matrix[0].size();
if(n==0)
{
return 0;
}
vector<vector<int> > dp(m+1,vector<int>(n+1,0));
for(int i=m-1;i>=0;--i)
{
for(int j=n-1;j>=0;--j)
{
if(matrix[i][j]=='1')
{
dp[i][j]=dp[i][j+1]>0?(dp[i][j+1]+1):1;
}
}
}
int max=0;
for(int i=0;i<m;++i)
{
for(int j=0;j<n;++j)
{
//calc max rectangle which uses i,j as the left upper corner
int tmp=0;
int k=i;
int pre=0;
while((k<m)&&(matrix[k][j]=='1'))
{
if(pre==0)
{
pre=dp[k][j];
}
else
{
pre=pre>dp[k][j]?dp[k][j]:pre;
}
if(pre*(k-i+1)>tmp)
{
tmp=pre*(k-i+1);
}
k++;
}
//
//cout<<"("<<i<<","<<j<<")="<<tmp<<endl;
if(tmp>max)
{
max=tmp;
}
}
}
return max;
}
};
解法3:借鉴上一题Largest Rectangle in Histogram中的思路,这题其实本质上和该题是类似的,不过是每次将matrix中的一列作为hist而已。
class Solution {
public:
int calcMaxRecInHist(int col,const vector<vector<int> >& dp)
{
int max=0;
stack<int> stk;
int i=0;
for(;i<dp.size();++i)
{
if((stk.empty())||(dp[stk.top()][col]<=dp[i][col]))
{
stk.push(i);
}
else
{
while((!stk.empty())&&(dp[stk.top()][col]>dp[i][col]))
{
int pos=stk.top();
stk.pop();
int extension=stk.empty()?pos:(pos-stk.top()-1);
int tmp=dp[pos][col]*(i-pos+extension);
if(tmp>max)
{
max=tmp;
}
}
stk.push(i);
}
}
while(!stk.empty())
{
int pos=stk.top();
stk.pop();
int extension=stk.empty()?pos:(pos-stk.top()-1);
int tmp=dp[pos][col]*(i-pos+extension);
if(tmp>max)
{
max=tmp;
}
}
return max;
}
int maximalRectangle(vector<vector<char> > &matrix) {
int m=matrix.size();
if(m==0)
{
return 0;
}
int n=matrix[0].size();
if(n==0)
{
return 0;
}
//prepare the dp matrix
vector<vector<int> > dp(m,vector<int>(n,0));
for(int i=m-1;i>=0;--i)
{
for(int j=n-1;j>=0;--j)
{
if(matrix[i][j]=='1')
{
if(((j+1)<n)&&(dp[i][j+1]>0))
{
dp[i][j]=dp[i][j+1]+1;
}
else
{
dp[i][j]=1;
}
}
}
}
int max=0;
//enum rectangle's left edge belongs to which column,then it becomes the same question as "Largest Rectangle in Histogram"
for(int i=0;i<n;++i)
{
//based on column i
int pmax=calcMaxRecInHist(i,dp);
if(pmax>max)
{
max=pmax;
}
}
return max;
}
};