给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
示例
输入:height = [0,1,0,2,1,0,1,3,2,1,2,1]
输出:6
解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水。
代码如下:
class Solution {
public:
int trap(vector<int>& height) { //每次移动较小的柱子,计算可以接水的量
int left=0,right=height.size()-1;
int leftmax=0,rightmax=0,result=0;
while(left<right){ //逻辑就是,每次计算小的柱子的接水量,和尚接水逻辑
if(height[left]<height[right]){
leftmax=max(leftmax,height[left]);
result+=leftmax-height[left]; //宽度为1,高度相差多少体积就为多少
left++;
}
else{
rightmax=max(rightmax,height[right]);
result+=rightmax-height[right];
right--;
}
}
}
return result;
}
};
过程描述
输入数据
以给出的 height = [0,1,0,2,1,0,1,3,2,1,2,1]
为例,解释如何一步步计算接到的雨水量。
初始化
使用双指针法,从数组两端开始:
left = 0
指向左端(位置 0)right = 11
指向右端(位置 11)leftMax = 0
:左边遇到的最大高度rightMax = 0
:右边遇到的最大高度result = 0
:存储最终接到的雨水量
步骤 1
- 当前
height[left] = 0
,height[right] = 1
- 因为
height[left] < height[right]
,我们考虑left
:- 更新
leftMax
,leftMax = max(leftMax, height[left]) = max(0, 0) = 0
- 雨水量为
leftMax - height[left] = 0 - 0 = 0
,没有水可以接 - 左指针向右移动:
left = 1
- 更新
步骤 2
- 当前
height[left] = 1
,height[right] = 1
- 因为
height[left] == height[right]
,我们考虑right
:- 更新
rightMax
,rightMax = max(rightMax, height[right]) = max(0, 1) = 1
- 雨水量为
rightMax - height[right] = 1 - 1 = 0
,没有水可以接 - 右指针向左移动:
right = 10
- 更新
步骤 3
- 当前
height[left] = 1
,height[right] = 2
- 因为
height[left] < height[right]
,我们考虑left
:- 更新
leftMax
,leftMax = max(leftMax, height[left]) = max(0, 1) = 1
- 雨水量为
leftMax - height[left] = 1 - 1 = 0
,没有水可以接 - 左指针向右移动:
left = 2
- 更新
步骤 4
- 当前
height[left] = 0
,height[right] = 2
- 因为
height[left] < height[right]
,我们考虑left
:- 更新
leftMax
,leftMax = max(leftMax, height[left]) = max(1, 0) = 1
- 雨水量为
leftMax - height[left] = 1 - 0 = 1
,可以接 1 个单位的雨水 - 更新
result = result + 1 = 0 + 1 = 1
- 左指针向右移动:
left = 3
- 更新
步骤 5
- 当前
height[left] = 2
,height[right] = 2
- 因为
height[left] == height[right]
,我们考虑right
:- 更新
rightMax
,rightMax = max(rightMax, height[right]) = max(1, 2) = 2
- 雨水量为
rightMax - height[right] = 2 - 2 = 0
,没有水可以接 - 右指针向左移动:
right = 9
- 更新
步骤 6
- 当前
height[left] = 2
,height[right] = 1
- 因为
height[left] > height[right]
,我们考虑right
:- 更新
rightMax
,rightMax = max(rightMax, height[right]) = max(2, 1) = 2
- 雨水量为
rightMax - height[right] = 2 - 1 = 1
,可以接 1 个单位的雨水 - 更新
result = result + 1 = 1 + 1 = 2
- 右指针向左移动:
right = 8
- 更新
步骤 7
- 当前
height[left] = 2
,height[right] = 2
- 因为
height[left] == height[right]
,我们考虑right
:- 更新
rightMax
,rightMax = max(rightMax, height[right]) = max(2, 2) = 2
- 雨水量为
rightMax - height[right] = 2 - 2 = 0
,没有水可以接 - 右指针向左移动:
right = 7
- 更新
步骤 8
- 当前
height[left] = 2
,height[right] = 3
- 因为
height[left] < height[right]
,我们考虑left
:- 更新
leftMax
,leftMax = max(leftMax, height[left]) = max(1, 2) = 2
- 雨水量为
leftMax - height[left] = 2 - 2 = 0
,没有水可以接 - 左指针向右移动:
left = 4
- 更新
步骤 9
- 当前
height[left] = 1
,height[right] = 3
- 因为
height[left] < height[right]
,我们考虑left
:- 更新
leftMax
,leftMax = max(leftMax, height[left]) = max(2, 1) = 2
- 雨水量为
leftMax - height[left] = 2 - 1 = 1
,可以接 1 个单位的雨水 - 更新
result = result + 1 = 2 + 1 = 3
- 左指针向右移动:
left = 5
- 更新
步骤 10
- 当前
height[left] = 0
,height[right] = 3
- 因为
height[left] < height[right]
,我们考虑left
:- 更新
leftMax
,leftMax = max(leftMax, height[left]) = max(2, 0) = 2
- 雨水量为
leftMax - height[left] = 2 - 0 = 2
,可以接 2 个单位的雨水 - 更新
result = result + 2 = 3 + 2 = 5
- 左指针向右移动:
left = 6
- 更新
步骤 11
- 当前
height[left] = 1
,height[right] = 3
- 因为
height[left] < height[right]
,我们考虑left
:- 更新
leftMax
,leftMax = max(leftMax, height[left]) = max(2, 1) = 2
- 雨水量为
leftMax - height[left] = 2 - 1 = 1
,可以接 1 个单位的雨水 - 更新
result = result + 1 = 5 + 1 = 6
- 左指针向右移动:
left = 7
- 更新
最终结果
此时 left == right
,循环结束,最终 result = 6
,表示可以接到的雨水总量为 6。