https://leetcode-cn.com/problems/trapping-rain-water/
思路一:维护一个单调非升的栈,栈中存储的是数组的下标,那么如果 h e i g h t [ i ] > h e i g h t [ s . t o p ( ) ] height[i]>height[s.top()] height[i]>height[s.top()],此时要判断一下栈中的元素是不是 > = 2 >=2 >=2的,因为 i i i作为右边界, s . t o p ( ) s.top() s.top()作为底部,还需要一个左边界才能计算贡献。贡献 = = =高度差 ∗ * ∗横坐标之差,注意细节问题。
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;
}
};
思路二: d p [ i ] dp[i] dp[i]表示在 i i i左侧的最大高度,那么对于某个位置 i i i,已知 d p [ i ] dp[i] dp[i],只要再知道 i i i右侧的最大高度,设为 M A X MAX MAX,如果 m i n ( M A X , d p [ i ] ) > h e i g h t [ i ] min(MAX,dp[i])>height[i] min(MAX,dp[i])>height[i],就对答案有贡献。所以再逆序处理一遍就可以了。
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;
}
};
思路三:两个指针,一个从左向右扫,一个从右向左扫,设 t m p = m i n ( a [ l ] , a [ r ] ) tmp=min(a[l],a[r]) tmp=min(a[l],a[r]),假设 a [ l ] = t m p a[l]=tmp a[l]=tmp,那么把 t m p tmp tmp当作左边界, a [ r ] a[r] a[r]当作右边界,移动 l l l统计贡献直到在某个位置有 a [ l ] > t m p a[l]>tmp a[l]>tmp,反之亦然。
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;
}
};