力扣LCR 039. 柱狀圖中最大的矩形

puningyyb發表於2024-07-22

思路
用到了單調棧。由於最大矩形它的高一定是height陣列中的其中一個值,那麼我們就可以遍歷陣列height的值再乘上它的寬的最大值WidthMax(寬的最大值後面會講),然後取最大值就是答案,也就是ans=max(ans,WidthMax*height[x])。
那麼如何求高為height[x]的寬的最大值WidthMax呢?
解題過程

如圖,以黃色塊為高所能撐起的最大範圍即為紅色部分,(陣列heigh中的每個值都有可能是黃色塊,所以後面要遍歷一下)那麼問題就轉變為:
1.求從x開始的左邊找第一個高度小於heigh[x]的長方形的下標l
2.同理,求從x的右邊第一個小於heigh[x]的長方形的下標r
3.矩形的寬的最大值為WidhMax = r -l -1

那麼問題又轉變為如何求上面的l和r?
對於求r,此問題不就是已知陣列的下標,求該下標開始從右邊開始找第一個更小值嗎?此時就可以用單調棧的思想來預處理每個點的右邊界的值了,該過程與力扣中https://leetcode.cn/problems/next-greater-element-i/description/這道題相似,不懂單調棧的可以先做那道題
那麼l也同理,從左邊開始找第一個更小值的下標
那麼r[x]和l[x]就求出來了,
最後遍歷每個小長方形,求(height[x]*(r[x]-l[x]-1))的最大值就是答案了

時間複雜度: 𝑂(𝑛)
空間複雜度: 𝑂(𝑛)

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        //選定一個下標,從這個下標兩邊分別找第一個比它矮的下標(理解為找左邊的第一個更小數,右邊的第一個更小數),然後r-l-1個這樣的矩形的和即為答案的可能之一
        const int N = 1e5+50;
        int l[N], r[N], s[N],top = -1;
        //預處理每個點的兩邊第一次碰到更矮的下標
        for(int i = 0; i < heights.size(); i++){
            int num = heights[i];
            while(top>=0&&heights[s[top]]>=num){
                top--;
            }
            if(top>=0)
                l[i] = s[top];
            else l[i] = -1;
            s[++top]=i;
        }
        top = -1;
        for(int i = heights.size()-1; i >= 0; i--){
            int num = heights[i];
            while(top>=0 && heights[s[top]] >= num)
                top--;
            if(top>=0) r[i] = s[top];
            else r[i] = heights.size();
            s[++top] = i;
        }
        int ans = 0;
        for(int i = 0; i < heights.size(); i++){
            ans = max(ans,(r[i]-l[i]-1)*heights[i]);
        }
        return ans;
    }
};

相關文章