题目
给定一个仅包含 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"]] 输出:0
示例 3:
输入:matrix = [["1"]] 输出:1
提示:
rows == matrix.length
cols == matrix[0].length
1 <= row, cols <= 200
matrix[i][j]
为'0'
或'1'
提交代码
//最大矩形
//单调栈
//求最大矩形的面积
//可以转换为->柱状图中最大的矩形
//分别以每行为柱子底,求柱子高度,然后找两侧第一个低于自己的柱子
//柱子的高度从最高为1逐渐递增
#include<iostream>
#include<vector>
#include<stack>
#include<algorithm>
using namespace std;
vector<vector<char>> matrix;//二维二进制矩阵
int result = 0;//结果
int rows;//行数
int cols;//列数
vector<int> height;//模拟柱子高度
stack<int> stk;//单调栈,存柱子下标
//利用单调栈找最大矩形,返回以该行为底的最大面积
int mr(int m){
int maxArea = 0;//最大面积
vector<int> left(cols),right(cols);//存左侧宽度,存右侧宽度
//确定柱子高度
for(int i = 0;i < cols;i++){
if(matrix[m][i] == '1'){
height[i]++;
}else{
height[i] = 0;
}
//printf("%d ",height[i]);
}
//printf("\n");
//压入-1,防止没有更矮的柱子
stk.push(-1);
//找左侧的第一个更矮的柱子
for(int i = 0;i < cols;i++){
while(!stk.empty()){
if(stk.top() == -1){
break;
}else if(height[i] <= height[stk.top()]){
stk.pop();
}else{
break;
}
}
left[i] = i - stk.top();//包括了自己的宽度
stk.push(i);
}
//弹空单调栈
while(!stk.empty()){
stk.pop();
}
//压入n,防止没有更矮的柱子
stk.push(cols);
//找右侧第一个更矮的柱子
for(int i = cols - 1;i >= 0;i--){
while(!stk.empty()){
if(stk.top() == cols){
break;
}else if(height[i] <= height[stk.top()]){
stk.pop();
}else{
break;
}
}
right[i] = stk.top() - i - 1;//去掉自己的宽度
maxArea = max(height[i] * (left[i] + right[i]),maxArea);
stk.push(i);
}
//弹空单调栈
while(!stk.empty()){
stk.pop();
}
return maxArea;
}
int main(){
//输入二维二进制矩阵
/*int h;
while(cin.peek() != '\n'){
scanf("%d",&h);
height.push_back(h);
}*/
char m;
while(cin.peek() != '^'){
vector<char> mx;
while(cin.peek() != '\n'){
//会把空格也读入,需排除空格
if(cin.peek() == ' '){
cin.ignore(1,' ');
continue;
}
scanf("%c",&m);
mx.push_back(m);
}
matrix.push_back(mx);
cin.ignore(1,'\n');
}
//-------------------------------
rows = matrix.size();//行数
cols = matrix[0].size();//列数
//将柱子高度均初始化为0
for(int i = 0;i < cols;i++){
height.push_back(0);
}
//循环模拟以每一行为第一行
int res;
for(int i = 0;i < rows;i++){
//利用单调栈找最大矩形
res = mr(i);
result = max(res,result);
}
//输出结果
printf("%d",result);
return 0;
}
总结
解题思路:这道题目涉及二维数组,假设共有rows行,可以拆解成rows个问题,分别以每一行为底,以第一行为顶,可以拆解成rows个柱状图中最大的矩形的一维问题,每次调用单调栈,找两侧更矮的柱子即可解决问题。