給定 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;
}
};