题目描述:
给定 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
方法1:备忘录
主要思路:
(1)对单个的位置进行分析,则该位置能够存储的雨水的数量,为其左边最高的高度和右边的最高的高度中的较小值减去当前高度后的值;
(2)根据上述思路,可以先声明两个数组,分别计算各个位置处的左边的最高高度和右边的最高高度,然后在遍历高度数组,使用最高高度数组中对应位置的较小值减去高度数组对应位置的值,即为该位置可以存储的雨水,将所有的雨水相加,即为结果;
class Solution {
public:
int trap(vector<int>& height) {
//处理特殊的情形
if(height.size()<3)
return 0;
//存储各个位置的左右最高高度值
vector<int> right_max(height.size(),0);
vector<int> left_max(height.size(),0);
//各个位置的右边的最高高度值
right_max[height.size()-1]=height[height.size()-1];
for(int i=height.size()-2;i>=0;--i){
right_max[i]=max(right_max[i+1],height[i]);
}
//各个位置的左边的最高高度值
left_max[0]=height[0];
for(int i=1;i<height.size();++i){
left_max[i]=max(left_max[i-1],height[i]);
}
//存储结果值
int sum=0;
//计算各个位置处可以存储的雨水值,并将其累加到sum
for(int i=0;i<height.size();++i){
sum+=min(right_max[i],left_max[i])-height[i];
}
return sum;
}
};
方法2:双指针
主要思路:
(1)主要思路和上述一致,只不过不需要计算每个位置的左右处的最大值中的最小值,而是计算相对的最小值即可,既能够满足存雨水即可;
class Solution {
public:
int trap(vector<int>& height) {
if(height.size()<3)
return 0;
int sum=0;
//分别从左右两端开始遍历
int left_max=height[0];
int right_max=height[height.size()-1];
int left=0;
int right=height.size()-1;
while(left<=right){//终止条件,既遍历完了所有的位置
//更新左右两边当前的能够获得最大值
left_max=max(left_max,height[left]);
right_max=max(right_max,height[right]);
//使用左右两边的值中的较小值作为存储雨水的边界值
if(left_max<right_max){
//将较小值减去对应位置的高度值,即为该位置能够存储的雨水值,将其累加到结果中
sum+=left_max-height[left++];
}
else{
sum+=right_max-height[right--];
}
}
return sum;
}
};