给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。

上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 感谢 Marcos 贡献此图。
解法一:Brute-Force, TLE
寻找左边最大值和右边最大值,取其小
class Solution {
public:
int trap(vector<int>& height) {
int n=height.size(),ans=0;
auto startit=cbegin(height), endit=cend(height);
for(int i=0;i<n;i++){
int l=*max_element(startit,startit+i+1);
int r=*max_element(startit+i, endit);
ans+=min(l,r)-height[i];
}
return ans;
}
}; 解法二 动态规划
避免解法一的多次运算左边最大和右边最大值
class Solution {
public:
int trap(vector<int>& height) {
int n=height.size(),ans=0;
vector<int> leftMax(height.size(),0),rightMax(height.size(),0);
for(int i=0;i<n;i++){
leftMax[i]=i==0?height[i]:max(leftMax[i-1],height[i]);
}
for(int i=n-1;i>=0;i--){
rightMax[i]=i==n-1?height[i]:max(rightMax[i+1],height[i]);
}
for(int i=0;i<n;i++){
ans+=min(leftMax[i],rightMax[i])-height[i];
}
return ans;
}
}; 解法三 双指针
原理同解法二,但因为从左至右和从右至左都是单调递增趋势(要找最大),所以可以使用双指针去解。
class Solution {
public:
int trap(vector<int>& height) {
int n=height.size();
if(n==0) return 0;
int l=0,r=n-1,max_l=height[l],max_r=height[r],ans=0;
while(l<r){
if(max_l<max_r){
ans+=max_l-height[l];
max_l=max(max_l,height[++l]);
}else{
ans+=max_r-height[r];
max_r=max(max_r,height[--r]);
}
}
return ans;
}
}; 
京公网安备 11010502036488号