LeetCode刷題筆記(貪心):maximal-rectangle



題目描述

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章