题目来源
题目描述
class Solution {
public:
int maximalRectangle(vector<vector<char>>& matrix) {
}
};
题目解析
暴力
遍历每个点,求以这个点位矩阵右下角的所有矩阵的面积。如下图两个例子,橙色是当前遍历的点,然后虚线框圈出的矩阵是其中一个矩阵
怎么找出这样的矩阵呢?如下图,如果我们知道了以这个点结尾的连续1的个数的话,问题就变得简单了
- 首先求出高度是1的矩阵面积,也就是它自身的数,如图橙色的4,面积就是4
- 然后向上扩展一行,高度增加一,选出当前列最小的数字,作为矩阵的宽,求出面积,对应上图的矩形框。
- 然后继续向上扩展,重复步骤 2。
按照上边的方法,遍历所有的点,求出所有的矩阵就可以了。
举个例子:以橙色的点为右下角
- 高度为 1
- 高度为 2
- 高度为 3
实现如下:
class Solution {
public:
int maximalRectangle(vector<vector<char>>& matrix) {
if(matrix.empty()){
return 0;
}
//保存以当前数字结尾的连续 1 的个数
int m = matrix.size(), n = matrix[0].size();
int width[m][n];
int maxArea = 0;
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
//更新 width
if(matrix[i][j] == '1'){
if(j == 0){
width[i][j] = 0;
}else{
width[i][j] = width[i][j - 1] + 1; //往左边看
}
}else{
width[i][j] = 0;
}
//记录所有行中最小的数
int minWidth = width[i][j];
//向上扩展行
for (int k = i; k >= 0; --k) {
int height = i - k + 1;
//找最小的数作为矩阵的宽
minWidth = std::min(minWidth, width[k][j]);
//更新面积
maxArea = std::max(maxArea, height * minWidth);
}
}
}
return maxArea;
}
};
单调栈
这道题是leetcode:84. 柱状图中最大的矩形的扩展
再想一下这个题,看下边的橙色的部分,这完全就是上一道题呀!
准备一个直方图数组
- 子矩阵必须以第0行作为地基的情况下(往上看),哪个子矩阵含有的1最多
- 得到[1、0、1、0、0],然后我们得到maxArea=1
- 子矩阵必须以第1行作为地基的情况下(往上看),哪个子矩阵含有的1最多
- 得到[2、0、2、1、1],然后我们得到maxArea=1+1+1=3
- 子矩阵必须以第2行作为地基的情况下(往上看),哪个子矩阵含有的1最多
- 得到[3、1、3、2、2],然后我们得到maxArea=2+2+2=6
- …
class Solution {
// height是正方图数组
int process(std::vector<int> & height){
if(height.empty()){
return 0;
}
int size = height.size();
int maxArea = 0;
std::stack<int> stack;
for (int i = 0; i < height.size(); ++i) {
while (!stack.empty() && height[i] <= height[stack.top()]){
int j = stack.top(); stack.pop();
int k = stack.empty() ? -1 : stack.top();
int currArea = (i - k - 1) * height[j];
maxArea = std::max(maxArea, currArea);
}
stack.push(i);
}
while (!stack.empty()){
int j = stack.top(); stack.pop();
int k = stack.empty() ? -1 : stack.top();
int currArea = (size - k - 1) * height[j];
maxArea = std::max(maxArea, currArea);
}
return maxArea;
}
public:
int maximalRectangle(vector<vector<char>>& matrix) {
if(matrix.empty()){
return 0;
}
//保存以当前数字结尾的连续 1 的个数
int m = matrix.size(), n = matrix[0].size();
int maxArea = 0;
std::vector<int> height(n, 0);
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
height[j] = matrix[i][j] == '0'? 0 : height[j] + 1;
}
maxArea = std::max(maxArea, process(height));
}
return maxArea;
}
};