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;
}
};