https://leetcode-cn.com/problems/trapping-rain-water/
思路一:維護一個單調非升的棧,棧中存儲的是數組的下標,那麼如果,此時要判斷一下棧中的元素是不是的,因爲作爲右邊界,作爲底部,還需要一個左邊界才能計算貢獻。貢獻高度差橫座標之差,注意細節問題。
class Solution {
public:
int trap(vector<int>& height) {
stack<int> s;
int ans=0;
for(int i=0;i<height.size();i++){
if(s.empty()||height[i]<=height[s.top()])
s.push(i);
else{
int tmp=s.top(),MIN;
s.pop();
while(!s.empty()&&height[s.top()]<height[i]){
ans+=(height[s.top()]-height[tmp])*(i-s.top()-1);
tmp=s.top();
s.pop();
}
if(!s.empty())
ans+=(height[i]-height[tmp])*(i-s.top()-1);
s.push(i);
}
}
return ans;
}
};
思路二:表示在左側的最大高度,那麼對於某個位置,已知,只要再知道右側的最大高度,設爲,如果,就對答案有貢獻。所以再逆序處理一遍就可以了。
class Solution {
public:
int trap(vector<int>& height) {
int MAX=0,ans=0;
vector<int> dp(height.size(),0);
for(int i=0;i<height.size();i++){
dp[i]=MAX;
MAX=max(MAX,height[i]);
}
MAX=0;
for(int i=height.size()-1;i>=0;i--){
dp[i]=min(dp[i],MAX);
MAX=max(MAX,height[i]);
if(dp[i]>height[i])
ans+=dp[i]-height[i];
}
return ans;
}
};
思路三:兩個指針,一個從左向右掃,一個從右向左掃,設,假設,那麼把當作左邊界,當作右邊界,移動統計貢獻直到在某個位置有,反之亦然。
class Solution {
public:
int trap(vector<int>& height) {
int l=0,r=height.size()-1,ans=0,tmp;
while(l<r){
tmp=min(height[l],height[r]);
if(tmp==height[l]){
++l;
while(l<r&&height[l]<=tmp)
ans+=tmp-height[l++];
}
else{
--r;
while(l<r&&height[r]<=tmp)
ans+=tmp-height[r--];
}
}
return ans;
}
};