給定 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
思路,雙指針法,找最大值max,表明最大值左邊水面只可能由左到右慢慢升高,最大值右邊水面只可能從右到左慢慢下降。
從最大值點把數組分成兩部分,[begin,maxposition]閉區間,[maxposition,end]這個問題簡化成一個問題,已知左/右邊最高,求能接多少雨水?不失一般性,另右邊最高,解左區間問題。單指針:
試想,這時,任何一點 i 的水面高度一定一定一定是從【0,i】之間的最大值,和峯值max之間的最小值(這句話好好理解!!),這樣問題就很簡單了,從0開始遍歷,一直更新我的leftmaxnum,如果需要更新,則這個點一定不存水,如果不更新,一定存leftmaxnum-height[i]高度的水,求和即可。
右區間同左。
代碼如下:
class Solution {
public:
int trap(vector<int>& height) {
if(height.size()==0) return 0;
int maxn=0;
auto maxloc=height.begin();
for(auto a=height.begin();a!=height.end();a++){
if(*a>maxn){
maxn=*a;maxloc=a;
}
}
auto leftpt = height.begin();
int leftmaxnum=height[0];
int sum=0;
while(leftpt!=maxloc){
if(*leftpt<leftmaxnum) sum+=(leftmaxnum-*leftpt);
else{leftmaxnum=*leftpt;}
leftpt++;
}
int rightmaxnum=0;
auto rightpt = height.end()-1;
while(rightpt!=maxloc){
if(*rightpt<rightmaxnum) sum+=(rightmaxnum-*rightpt);
else{rightmaxnum=*rightpt;}
rightpt--;
}
return sum;
}
};