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

css
输入: 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 个单位的雨水(蓝色部分表示雨水)。
示例 2:
css
输入: height = [4,2,0,3,2,5]
输出: 9
提示:
n == height.length
1 <= n <= 2 * 104
0 <= height[i] <= 105
二、题解(双指针)
js
/**
* @param {number[]} height
* @return {number}
*/
var trap = function(height) {
let left = 0;
let right = height.length - 1;
let leftMax = 0;
let rightMax = 0;
let ans = 0;
while (left < right) {
if (height[left] < height[right]) {
height[left] >= leftMax
? leftMax = height[left]
: ans += leftMax - height[left];
left++;
} else {
height[right] >= rightMax
? rightMax = height[right]
: ans += rightMax - height[right];
right--;
}
}
return ans;
};
核心思想(双指针)
-
双指针法: 使用两个指针
left
和right
分别从数组的两端向中间移动。 -
短板效应与动态维护最大高度:
- 短板效应: 每个位置能够接到的雨水高度,取决于它左右两侧最大高度的 较小值(也就是"短板")。 就像木桶原理一样,水位的高度取决于最短的那块木板。
- 动态维护最大高度: 通过
leftMax
维护左侧的最大高度,通过rightMax
维护右侧的最大高度。在移动指针的过程中,不断更新这两个变量。 - 计算雨水: 每次移动指针,都判断当前位置可以接到的雨水,并累加到
ans
中。如果当前高度小于两侧的最大高度,就可以接到雨水。 雨水的高度等于较小侧的最大高度减去当前高度。如果当前高度大于两侧最大高度,则更新最大高度。
一些细节
-
为什么移动较小的一侧?
- 每次比较
height[left]
和height[right]
,总是移动 较小的那一侧 。 这是因为只有移动较小的一侧,才 有可能 遇到更高的柱子,从而抬高短板,增加能够接到的水量。 如果移动较大的一侧,短板仍然是较小的一侧,接水量不会增加。
- 每次比较
-
根据短板计算雨水:
- 如果
height[left] < height[right]
,那么left
指针的位置能接到的水量,是由左边的最大高度leftMax
决定的。计算公式为leftMax - height[left]
。 - 如果
height[left] >= height[right]
,那么right
指针的位置能接到的水量,是由右边的最大高度rightMax
决定的。计算公式为rightMax - height[right]
。
- 如果
三、结语
再见!