單調棧系列-Leetcode 84. 柱狀圖中最大的矩形

問題描述

給定 n 個非負整數,用來表示柱狀圖中各個柱子的高度。每個柱子彼此相鄰,且寬度爲 1 。

求在該柱狀圖中,能夠勾勒出來的矩形的最大面積。
在這裏插入圖片描述
以上是柱狀圖的示例,其中每個柱子的寬度爲 1,給定的高度爲 [2,1,5,6,2,3]
在這裏插入圖片描述
圖中陰影部分爲所能勾勒出的最大矩形面積,其面積爲 10 個單位。[1]^{[1]}

示例:

輸入: [2,1,5,6,2,3]
輸出: 10

解題報告

維持一個 單調遞增棧,當前元素小於棧頂元素時,以棧頂元素爲高度的矩形就無法向右邊擴展了,所以就可以計算以棧頂元素爲高度的最大矩形面積。

當然了,這題還有一些編程的技巧性,即設置 哨兵。這樣做有什麼好處呢?

  • 因爲在求以棧頂元素爲高度的最大矩形時,右邊界是當前元素的索引,左邊界是棧頂元素的上一個元素,爲什麼是棧頂元素的上一個元素,因爲當出現 [3, 6, 7, 4, 2]這樣的柱狀圖,遍歷到 4 時,會陸續計算以 76 爲高度的最大矩形面積,然後將 4 壓棧,但是在計算以 4 爲高度的最大矩形面積時,右邊界是 4, 這時左邊界爲 0, 而不是 3。但是這樣就會帶來一個問題,當棧中只剩下一個元素時,左邊界應該爲該元素的前一個元素, 即爲 0,與棧中只剩一下元素矛盾,除非特殊處理,爲了統一處理,在棧中加入 哨兵 0
  • 當遍歷到最後一個元素,以最後一個元素爲高度的最大矩形面積不好確定右邊界,爲了統一處理,在原始數組的末尾加入 哨兵 0

實現代碼

class Solution{
    public:
        int largestRectangleArea(vector<int>& heights)
        {
            int ans = 0;
            stack<int> stk;
            stk.push(0);
            heights.insert(heights.begin(), 0);
            heights.push_back(0);
            for (int i = 1; i < heights.size(); i++)
            {
                // 每當遇到棧頂元素大於當前元素時,以棧頂元素爲高度的矩形必定不能向右擴展
                // 所以當前需要先計算以棧頂元素爲高度的矩形高度
                while (heights[stk.top()] > heights[i])
                {
                    int cur = stk.top();
                    stk.pop();
                    ans=max(ans, heights[cur]*(i-stk.top()-1));
                }
                stk.push(i);
            }
            return ans;
        }
};
$^{[2]}$

參考資料

[1] Leetcode 84. 柱狀圖中最大的矩形
[2] 題解區:Ikaruga

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