(單調棧)42. 接雨水

給定 n 個非負整數表示每個寬度爲 1 的柱子的高度圖,計算按此排列的柱子,下雨之後能接多少雨水。

上面是由數組 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度圖,在這種情況下,可以接 6 個單位的雨水(藍色部分表示雨水)。 感謝 Marcos 貢獻此圖。

示例:

輸入: [0,1,0,2,1,0,1,3,2,1,2,1]
輸出: 6

來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/trapping-rain-water
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。
 

題解:在51nod上做過類似的題,所以1A。首先明確每根柱子可以嘗試去做凹坑的左邊,那麼,只需要找到凹坑的右邊最優柱子即可。右邊柱子有兩種情況:   

            假設:左邊柱子A;右邊柱子B

            情況一:B要大於等於A的高度,纔有可能形成凹坑

                           3     2      2     4     2    3

                           A                     B

            情況二:B小於A的高度,但是B柱子是A柱子右邊所有柱子的最高的那一個 

                           5      3     3      3     4     2    3

                           A                              B

            整體複雜度O(N)

class Solution {
public:
    int fun(vector<int>& a,int x,int y){
        int d = min(a[x],a[y]),ans = 0;
        for(int i=x+1;i<y;i++) ans += d-a[i];
        return ans;
    }

    int trap(vector<int>& a) {
        int len = a.size();
        if(!len) return 0;
        vector<int>maxx;
        for(int i=0;i<len;i++) maxx.push_back(a[i]);
        // 查找右邊最大值的下標
        int x = maxx[len-1],y = len-1;
        maxx[len-1] = len;
        for(int i=len-2;i>=0;i--){
            int xx = x,yy = y;
            if(x<=maxx[i]){
                xx = maxx[i],yy = i;
            }
            maxx[i] = y;
            x = xx; y = yy;
        }

        // 查找右邊第一個比a[i]大的下標
        vector<int>r(len);
        stack<int>s;
        for(int i=len-1;i>=0;i--){
            while(s.size()&&a[s.top()]<a[i]) s.pop();
            if(s.size()) r[i] = s.top();
            else r[i] = len;
            s.push(i);
        }

        int i = 0,ans = 0;
        while(i < len){
            if(!a[i]){ i++; continue; }
            int j = i;
            if(r[i] == len) j = maxx[i];
            else j = r[i];
            if(j == len) break;
            ans += fun(a,i,j);
            i = j;
        }
        return ans;
    }
};

 

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