- 轉載請註明作者和出處:http://blog.csdn.net/u011475210
- 代碼地址:https://github.com/WordZzzz/Note/tree/master/LeetCode
- 刷題平臺:https://www.nowcoder.com/ta/leetcode
- 題 庫:Leetcode經典編程題
- 編 者:WordZzzz
題目描述
Given a 2D binary matrix filled with 0’s and 1’s, find the largest rectangle containing all ones and return its area.
給定一個用0和1填充的2D二進制矩陣,找到包含所有1的最大矩形並返回其面積。
解題思路
剛看到這道題的時候,一臉無奈。我們還是先來看一下Largest Rectangle in Histogram這道題目吧。
Largest Rectangle in Histogram
Given n non-negative integers representing the histogram’s bar height where the width of each bar is 1, find the area of largest rectangle in the histogram.
Above is a histogram where width of each bar is 1, given height = [2,1,5,6,2,3].
The largest rectangle is shown in the shaded area, which has area = 10 unit.
For example,
Given heights = [2,1,5,6,2,3],
return 10.
我們先把代碼貼出來,然後邊看代碼邊捋清思路。
class Solution {
public:
int largestRectangleArea(vector<int>& height) {
stack<int> s;
height.push_back(0);//追加一個零用來做終止條件。
int maxSize = 0;
int i = 0;
while(i < height.size()){
if(s.empty() || height[i] >= height[s.top()])
s.push(i++);
else{
int cur = height[s.top()];
s.pop();
maxSize = max(maxSize, cur * (s.empty() ? i : i - 1 - s.top()));
}
}
return maxSize;
}
};
- 首先,我們需要新建stack來保存遍歷過程中的遞增序列。如果棧是空的,那麼索引i入棧。所以當i=0時,將0入棧。注意棧內保存的是索引,不是高度。然後i++。
- 當i=1的時候,發現height[i]小於了棧內的元素,於是出棧。這時候stack爲空,所以面積的計算是height[t] * i。t是剛剛彈出的stack頂元素。也就是藍色部分的面積。
- 這時候stack爲空了,那就繼續入棧。注意到只要是連續遞增的序列,我們都要keep pushing,直到我們遇到了i=4,height[i]=2小於了棧頂的元素。
- 這時候開始計算矩形面積。首先彈出棧頂元素,t=3。即下圖綠色部分。
- 接下來注意到棧頂的(索引指向的)元素還是大於當前i指向的元素,於是出棧,並繼續計算面積,桃紅色部分。
- 最後,棧頂的(索引指向的)元素大於了當前i指向的元素,循環繼續,入棧並推動i前進。直到我們再次遇到下降的元素,也就是我們最後人爲添加的dummy元素0.
- 同理,我們計算棧內的面積。由於當前i是最小元素,所以所有的棧內元素都要被彈出並參與面積計算。
注意我們在計算面積的時候已經更新過了maxSize 。
我們可以看到,stack中總是保持遞增的元素的索引,然後當遇到較小的元素後,依次出棧並計算棧中bar能圍成的面積,直到棧中元素小於當前元素。
maximal-rectangle
這道題的解法靈感來自於Largest Rectangle in Histogram這道題,假設我們把矩陣沿着某一行切下來,然後把切的行作爲底面,將自底面往上的矩陣看成一個直方圖(histogram)。直方圖的中每個項的高度就是從底面行開始往上1的數量。根據Largest Rectangle in Histogram中的largestRectangleArea函數我們就可以求出當前行作爲矩陣下邊緣的一個最大矩陣。接下來如果對每一行都做一次Largest Rectangle in Histogram,從其中選出最大的矩陣,那麼它就是整個矩陣中面積最大的子矩陣。算法時間複雜度爲O(m*n),這解法真是太棒了,其實應該算是動態規劃的題目了。
C++版代碼實現
class Solution {
public:
class Solution {
public:
int largestRectangleArea(vector<int>& height) {
stack<int> s;
height.push_back(0);//追加一個零用來做終止條件。
int maxSize = 0;
int i = 0;
while(i < height.size()){
if(s.empty() || height[i] >= height[s.top()])
s.push(i++);
else{
int cur = height[s.top()];
s.pop();
maxSize = max(maxSize, cur * (s.empty() ? i : i - 1 - s.top()));
}
}
return maxSize;
}
};
int maximalRectangle(vector<vector<char> > &matrix) {
if(matrix.empty())
return 0;
int maxRec = 0;
vector<int> height(matrix[0].size(), 0);
for(int i = 0; i < matrix.size(); ++i){
for(int j = 0; j < matrix[0].size(); ++j){
if(matrix[i][j] == '1')//這裏的數字1一定要加單引號哦~
height[j]++;
else
height[j] = 0;
}
maxRec = max(maxRec, largestRectangleArea(height));//對每一行都求一次最大值,而不是隻有最後一行。
}
return maxRec;
}
};
系列教程持續發佈中,歡迎訂閱、關注、收藏、評論、點贊哦~~( ̄▽ ̄~)~
完的汪(∪。∪)。。。zzz