leetcode - [棧] -柱狀圖中的最大矩形(84)

1、問題描述

給定n個非負整數,用來表示柱狀圖中每個柱子的高度。每個柱子彼此相鄰,且寬度爲1.
求柱狀圖中能勾勒出的最大面積。
在這裏插入圖片描述
以上是柱狀圖的示例,其中每個柱子的寬度爲 1,給定的高度爲 [2,1,5,6,2,3]。
在這裏插入圖片描述
圖中陰影部分爲所能勾勒出的最大矩形面積,其面積爲 10 個單位。

2、解題思路

方法1暴力法。在柱子ii和柱子jj構成的區間中,最大的矩形面積爲區間長度*區間內最矮柱子的高度,即(ji+1)×min{height}(j-i+1) \times min\{height\},因此我們可以枚舉所有的區間,然後找到每個區間的最小值,並計算該區間內最大矩形的面積。最後這些面積中選擇最大的那個。
這種方法的時間複雜度爲O(n3)O(n^3)。枚舉所有的區間需要O(n2)O(n^2)的時間複雜度,在區間中尋找最小值需要O(n)O(n)的時間複雜度。空間複雜度爲O(1)O(1)

方法2暴力法的優化。對於每個區間,上述暴力法都會掃描一遍以找到最小值,但其實這不是必須的,比如對於[2,0,1][2,0,1][2,0,1,3][2,0,1,3]這兩個區間,由於後一個區間包含前一個區間,故後一個區間的最小值很有可能和前一個區間相等,因此在求後一個區間的最小值時,只需將後一個區間拓展的元素和前一個區間的最小值比較,如果小於則更新該區間的最小值。
這種方法的時間複雜度爲O(n2)O(n^2),空間複雜度爲O(1)O(1)

方法3單調棧。我們可以換個角度來看這個問題。以[1,2,4,5,3][1,2,4,5,3]爲例:
對於高度爲4的柱子而言,如何計算以4爲高度的矩形的最大面積?
很顯然,我們需要找到柱子4的左、右邊界。然後計算它的高度與左右邊界形成的區間的乘積。
什麼是它的左右邊界? 左邊第一個高度小於它的柱子就是它的左邊界,右邊第一個高度大於它的柱子就是它的右邊界。
像這種涉及nextgreaternextgreaternextsmallernextsmaller的問題,都可以使用單調棧來解決。維持一個單調遞增棧,對於棧頂元素height[s(top)]height[s(top)],次棧頂元素即爲它的左邊界(即左邊第一個小於它的元素),如果當前遍歷元素height[current]height[current]大於棧頂元素,那麼當前元素即爲它的左邊界,這時可以求得以棧頂元素作爲高的矩形最大面積爲:
area=height[s(top)]×(currents(top1)1)area = height[s(top) ] \times (current - s(top - 1) - 1)
注意,當遍歷完最後一個元素時,
對於棧中剩下的每個元素,以其爲高構成的最大矩形面積爲:
area=height[s(top)]×(height.lengths(top1)1)area = height[s(top)] \times(height.length - s(top-1)-1)
對於該算法的動態演化過程,可參考:例子動態演示
這種方法的時間複雜度爲O(n)O(n),空間複雜度爲O(n)O(n).

3、代碼實現

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        int len = heights.size();
        int maxarea = 0;
        stack<int> s;
        s.push(-1);
        for(int i = 0; i < len; i++){
            while(s.top() != -1 && heights[i] < heights[s.top()]){
                int top = s.top();
                s.pop();
                maxarea = max(maxarea, heights[top] * (i - s.top() - 1));
            }
            s.push(i);
        }
        while(s.top() != -1){
            int top = s.top();
            s.pop();
            maxarea = max(maxarea, heights[top] * (len - s.top() - 1));
        }
        return maxarea;
        
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章