给定一个仅包含 0 和 1 、大小为 rows x cols 的二维二进制矩阵,找出只包含 1 的最大矩形,并返回其面积。
示例 1:
输入:matrix = [[“1”,“0”,“1”,“0”,“0”],[“1”,“0”,“1”,“1”,“1”],[“1”,“1”,“1”,“1”,“1”],[“1”,“0”,“0”,“1”,“0”]]
输出:6
解释:最大矩形如上图所示。
示例 2:
输入:matrix = []
输出:0
示例 3:
输入:matrix = [[“0”]]
输出:0
示例 4:
输入:matrix = [[“1”]]
输出:1
示例 5:
输入:matrix = [[“0”,“0”]]
输出:0
class Solution {
public:
int maximalRectangle(vector<vector<char>>& matrix) {
int m=matrix.size(),n=matrix[0].size();//记录矩阵的长和宽
vector<int> height(n,0);//存储以当前行为下边界,每一列的高度(从当前行向上数连续1的个数)
//当前行开始连续1的个数,实际上为上一行对应位置的数字加上当前行的判断。如果当前行对应位置为0,则为0;如果为1,则为上一行对应位置个数加1
int result=0;
for(int i=0;i<m;i++)
{
//以每一行为坐标轴,计算当前当前行及以上位置,柱状图中的最大矩形面积
//for循环确定柱状图中每个位置的高度
for(int j=0;j<n;j++)
{
if(matrix[i][j]=='1')
{
height[j]++;
}else height[j]=0;
}
//确定当前行及以上的最大矩形面积
result = max(result, maxRectangle(height));
}
return result;
}
//确定当前行及以上的最大矩形面积
int maxRectangle(const vector<int>& height)
{
stack<int> index;//栈,存储height数组的下标
int result=0;//最大矩形面积
int n=height.size();
//遍历数组,计算以每一个数字为高时的最大矩形面积,在其中取最大值
for(int i=0;i<n;i++)
{
//如果栈非空,且当前元素的高度小于栈顶元素高度,则栈顶元素找到了右边界,此时计算矩形高度
//栈顶元素的左边界就是栈中的倒数第二个元素
while(!index.empty()&&height[i]<height[index.top()])
{
int he=height[index.top()];//记录当前矩形高度
index.pop();//弹栈
int len=i;//记录当前矩形宽
if(!index.empty()) len=i-index.top()-1;
result=max(result,he*len);
}
index.push(i);
}
//此时i已经遍历全部数组,栈中剩余元素单调递增,且右边界均为n。计算矩形面积,更新最大值
while(!index.empty())
{
int he=height[index.top()];
index.pop();
if(index.empty()) result=max(result,he*n);
else result=max(result,he*(n-index.top()-1));
}
return result;
}
};
时间复杂度O(mn)
空间复杂度O(n)
思路
法一:代码优化,在height数组的首尾添加哨兵
class Solution {
public:
int maximalRectangle(vector<vector<char>>& matrix) {
int m=matrix.size(),n=matrix[0].size();
vector<int> height(n,0);
int result=0;
for(int i=0;i<m;i++)
{
for(int j=0;j<n;j++)
{
if(matrix[i][j]=='1')
{
height[j]++;
}else height[j]=0;
}
result = max(result, maxRectangle(height));
}
return result;
}
//在height数组的首尾添加哨兵0,计算矩形长度时不用判断栈空
int maxRectangle(const vector<int>& height)
{
stack<int> index;
int result=0;
vector<int> height2(height);
height2.push_back(0);
height2.insert(height2.begin(),0);
int n=height2.size();
index.push(0);
for(int i=1;i<n;i++)
{
while(!index.empty()&&height2[i]<height2[index.top()])
{
int he=height2[index.top()];
index.pop();
int len=i-index.top()-1;
result=max(result,he*len);
}
index.push(i);
}
return result;
}
};
class Solution {
public:
int maximalRectangle(vector<vector<char>>& matrix) {
if(matrix.empty()) return 0;//去除矩阵为空的情况
int m=matrix.size(),n=matrix[0].size();
//H[i]表示当前行i处矩形对应的高,L[i]表示当前左边离i处最近的字符0的下标,R[i]表示当前右边离i处最近的字符0的下标
//为了避免边界问题导致出错,选择L数组中-1作为标志位,选择R数组中n作为标志位
vector<int> H(n,0),L(n,-1),R(n,n);
int result=0;//记录当前的最大矩形面积
//每一层for循环记录当前行及以上的最大矩形面积
for(int i=0;i<m;i++)
{
int left=-1,right=n;//left为当前已经访问过的字符中最右边0对应的下标,right为从右往左访问过的字符中最左边0对应的下标
//填L数组和H数组,从左往右遍历当前行
for(int j=0;j<n;j++)
{
if(matrix[i][j]=='1')//如果为1,当前位置矩形的高度为上一行高度加1,距离当前位置最近的0的下标为上一行当前位置最近的0和left,二者取较大值
{
H[j]++;
L[j]=max(L[j],left);
}else{//如果为0,更新left的值,当前位置的矩形高度为0,距离当前位置最近的0的下标置为标志位
left=j;
H[j]=0;L[j]=-1;
}
}
//填R数组然后计算当前矩形的面积
for(int j=n-1;j>=0;j--)
{
if(matrix[i][j] == '1')//如果当前数字为1,更新R数组,计算矩形面积
{
R[j]=min(R[j],right);
result=max(result,H[j]*(R[j]-L[j]-1));
}else{//如果为0,更新right和R数组对应位置为标志位
right=j;
R[j]=n;
}
}
}
return result;
}
};