一、题目描述

二、解题方法
可以参考这个佬的帖子:
接雨水的四种姿势------一篇文章彻底弄懂接雨水问题-CSDN博客
整体思路:雨水量按列计算,每一列的储水量为min([0,i]最高的高度,[i,n-1]最高的高度)-height[i],如果这个值为正数,表示可以接雨水,加上这个差值就行,否则就无法储水,加上0。
1>解法一:遍历
暴力法是针对每一个height[i],分别向左、向右寻找最大高度,再进行按列计算,因此时间复杂度为O(n*n),我们可以预处理两个数组,leftMax[i]表示[0,i]的最大高度,rightMax[i]表示[i,n-1]的最大高度,再遍历height数组进行计算,3次遍历,将时间复杂的降低为O(n);
2>解法二:双指针
针对解法一,我们可以再一次进行优化,即无需进行3次遍历,使用对撞双指针,一边移动指针,一边进行计算,因此只需要进行一次遍历即可。
三、代码实现
1>解法一:遍历
cpp
class Solution {
public:
int trap(vector<int>& height) {
//三次遍历
int n=height.size();
//leftMax[i]表示从[0,i]的最高高度
vector<int> leftMax(n);
int left_max=0;
for(int index=0;index!=n;index++){
left_max=max(left_max,height[index]);
leftMax[index]=left_max;
}
//rightMax[i]表示从[0,i]的最高高度
vector<int> rightMax(n);
int right_max=0;
for(int index=n-1;index>=0;index--){
right_max=max(right_max,height[index]);
rightMax[index]=right_max;
}
//遍历hegiht数组,按列结算
int rain=0;
for(int index=0;index!=n;index++)
rain+=min(leftMax[index],rightMax[index])-height[index];
return rain;
}
};
2>解法二:双指针
cpp
class Solution {
public:
int trap(vector<int>& height) {
//双指针
int n=height.size();
int left=0,right=n-1,rain=0;
int left_max=0,right_max=0;
while(left<right){
left_max=max(left_max,height[left]);
right_max=max(right_max,height[right]);
//结算较矮的那边(每次只动一边)
//左边<=右边(结算左边)
if(left_max<=right_max)
rain+=left_max-height[left++];
//右边<左边(结算右边)
else if(right_max<left_max)
rain+=right_max-height[right--];
}
return rain;
}
};