Maximal Square
Given a 2D binary matrix filled with 0’s and 1’s, find the largest square containing only 1’s and return its area.
Example:
Input:
1 0 1 0 0
1 0 1 1 1
1 1 1 1 1
1 0 0 1 0
Output: 4
解法
动态规划,找到每一个位置的可以达到的最大的正方形的边长。
class Solution {
public:
int maximalSquare(vector<vector<char>>& matrix) {
if(matrix.empty() || matrix[0].empty())
return 0;
int m = matrix.size();
int n = matrix[0].size();
vector<vector<int> > dp(m, vector<int> (n, 0));
int res = 0;
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(i == 0 || j == 0)
dp[i][j] = matrix[i][j] == '1' ? 1:0;
else{
if(matrix[i][j] == '1')
dp[i][j] = min(dp[i][j-1],min(dp[i-1][j],dp[i-1][j-1])) + 1;
else
dp[i][j] = 0;
}
res = max(res, dp[i][j]);
}
}
return res*res;
}
};
Maximal Rectangle
Given a 2D binary matrix filled with 0’s and 1’s, find the largest rectangle containing only 1’s and return its area.
Example:
Input:
[
[“1”,“0”,“1”,“0”,“0”],
[“1”,“0”,“1”,“1”,“1”],
[“1”,“1”,“1”,“1”,“1”],
[“1”,“0”,“0”,“1”,“0”]
]
Output: 6
直方图中最大的面积
可以把这个问题变成求直方图中最大的矩形面积;
对矩阵的每一行加上这行之前的所有行构成一个直方图heights,如果当前值为1,则heights[j]++,否则为0
对每一个直方图进行求最大面积值,最后得到的所有直方图的最大面积就是结果。
class Solution {
public:
int maximalRectangle(vector<vector<char>>& matrix) {
if(matrix.empty() || matrix[0].empty())
return 0;
int m = matrix.size();
int n = matrix[0].size();
vector<int> heights(n, 0);
int res = 0;
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(matrix[i][j] == '1')
heights[j] ++;
else
heights[j]= 0;
}
res = max(res,LargeRecinHisto(heights));
}
return res;
}
int LargeRecinHisto(vector<int> heights){
stack<int> s;
heights.push_back(0);
int max_value = 0;
for(int i=0;i<heights.size();i++){
if(s.empty() || heights[i] >= heights[s.top()])
s.push(i);
else{
while(!s.empty() && heights[i] < heights[s.top()]){
int cur = s.top();
s.pop();
max_value = max(max_value, heights[cur]*(s.empty() ? i : i-s.top()-1));
}
s.push(i);
}
}
return max_value;
}
};
一个函数解决
class Solution {
public:
int maximalRectangle(vector<vector<char>>& matrix) {
if(matrix.empty() || matrix[0].empty())
return 0;
int m = matrix.size();
int n = matrix[0].size();
vector<int> heights(n+1, 0);
int res = 0;
for(int i=0;i<m;i++){
stack<int> s;
for(int j=0;j<n+1;j++){
if(j<n)
heights[j] = matrix[i][j] == '1' ? heights[j]+1:0;
while(!s.empty() && heights[j] <= heights[s.top()]){
int cur = s.top();
s.pop();
res = max(res, heights[cur]*(s.empty() ? j : j-s.top()-1));
}
s.push(j);
}
}
return res;
}
};
解法2
构造一个heights数组和解法1相同,然后再构造一个left和right数组
left数组表示:如果当前值matrix[i][j]==1,left[j]为与其相连都为1的左边界位置,否则为0;
right数组表示:如果当前值matrix[i][j]==1,right[j]为与其相连都为1的右边界位置+1,否则为n;
对于任意一个位置的[i][j],面积表示为(right[j]-left[j])*heights[j]。
举个栗子:
[
[1, 1, 0, 0, 1],
[0, 1, 0, 0, 1],
[0, 0, 1, 1, 1],
[0, 0, 1, 1, 1],
[0, 0, 0, 0, 1]
]
第0行:
h: 1 1 0 0 1
l: 0 0 0 0 4
r: 2 2 5 5 5
第1行:
h: 0 2 0 0 2
l: 0 1 0 0 4
r: 5 2 5 5 5
第2行:
h: 0 0 1 1 3
l: 0 0 2 2 4
r: 5 5 5 5 5
第3行:
h: 0 0 2 2 4
l: 0 0 2 2 4
r: 5 5 5 5 5
第4行:
h: 0 0 0 0 5
l: 0 0 0 0 4
r: 5 5 5 5 5
class Solution {
public:
int maximalRectangle(vector<vector<char>>& matrix) {
if(matrix.empty() || matrix[0].empty())
return 0;
int m = matrix.size();
int n = matrix[0].size();
vector<int> heights(n, 0), left(n, 0), right(n, n);
int res = 0;
for(int i=0;i<m;i++){
int cur_left = 0, cur_right = n;
for(int j=0;j<n;j++){
if(matrix[i][j] == '1'){
heights[j]++;
left[j] = max(left[j], cur_left);
}
else{
heights[j] = 0;
left[j] = 0;
cur_left = j+1;
}
}
for(int j=n-1;j>=0;j--){
if(matrix[i][j] == '1')
right[j] = min(right[j], cur_right);
else{
right[j] = n;
cur_right = j;
}
res = max(res, (right[j] - left[j]) * heights[j]);
}
}
return res;
}
};
解法3
先统计每一行的连续1的个数,使用一个数组 h_max, 其中 h_max[i][j] 表示第i行,第j个位置水平方向连续1的个数,若 matrix[i][j] 为0,那对应的 h_max[i][j] 也一定为0;
再次遍历每个位置,首先每个位置的 h_max 值都先用来更新结果 res,因为高度为1也可以看作是矩形,然后我们向上方遍历,上方 (i, j-1) 位置也会有 h_max 值,但是用二者之间的较小值才能构成矩形,用新的矩形面积来更新结果 res,这样一直向上遍历,直到遇到0,或者是越界的时候停止,这样就可以找出所有的矩形了。
class Solution {
public:
int maximalRectangle(vector<vector<char>>& matrix) {
if(matrix.empty() || matrix[0].empty())
return 0;
int m = matrix.size();
int n = matrix[0].size();
vector<vector<int> > h_max(m, vector<int> (n,0));
int res = 0;
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if (matrix[i][j] == '0') continue;
if (j > 0) h_max[i][j] = h_max[i][j - 1] + 1;
else h_max[i][0] = 1;
}
}
for(int i=0;i<m;i++){
for (int j = 0; j < n; ++j) {
if (h_max[i][j] == 0) continue;
int mn = h_max[i][j];
res = max(res, mn);
for (int k = i - 1; k >= 0 && h_max[k][j] != 0; --k) {
mn = min(mn, h_max[k][j]);
res = max(res, mn * (i - k + 1));
}
}
}
return res;
}
};