【每日一题】LeetCode 40.接雨水
题目描述
给定 n
个非负整数,每个整数代表一个柱子的高度,这些柱子按照宽度为 1 的方式排列。我们需要计算在下雨之后,这些柱子能够接住多少雨水。
思路分析
这个问题可以通过双指针法来解决。我们使用两个指针 left
和 right
分别从数组的两端向中间遍历。同时,我们维护两个变量 leftMax
和 rightMax
来记录从左到右和从右到左遍历时遇到的最大高度。
- 初始化:设置两个指针
left
和right
分别指向数组的起始和结束位置,leftMax
和rightMax
初始化为 0。 - 遍历:在
left < right
的条件下,进行循环。- 如果
height[left] < height[right]
,说明当前的雨水可能流向左边的柱子,我们更新leftMax
并计算左边的积水量。 - 反之,如果
height[left] >= height[right]
,则雨水可能流向右边的柱子,我们更新rightMax
并计算右边的积水量。
- 如果
- 更新指针:根据上述比较结果,移动
left
或right
指针。 - 计算积水量:如果当前柱子的高度小于对应的
leftMax
或rightMax
,则当前柱子上可以积水,积水量为两者的较小值减去当前柱子的高度。
输入示例
示例 1
- 输入:
height = [0,1,0,2,1,0,1,3,2,1,2,1]
- 输出:
6
示例 2
- 输入:
height = [4,2,0,3,2,5]
- 输出:
9
代码实现
class Solution {
public int trap(int[] height) {
// 如果数组为空,直接返回0
if (height.length == 0) return 0;
// 初始化左右指针和左右最大高度
int left = 0, right = height.length - 1;
int leftMax = 0, rightMax = 0;
int count = 0; // 用于记录积水总量
// 当左右指针不相遇时,继续遍历
while (left < right) {
// 如果左边柱子矮,则更新leftMax,并计算积水
if (height[left] < height[right]) {
if (height[left] >= leftMax) {
// 更新左边的最大高度
leftMax = height[left];
} else {
// 计算左边的积水量,并累加到count
count += leftMax - height[left];
}
left++; // 移动左指针
}
// 如果右边柱子矮或一样高,则更新rightMax,并计算积水
else {
if (height[right] >= rightMax) {
// 更新右边的最大高度
rightMax = height[right];
} else {
// 计算右边的积水量,并累加到count
count += rightMax - height[right];
}
right--; // 移动右指针
}
}
// 返回积水总量
return count;
}
}
题外话:在计算机科学的世界里,即使是最矮的柱子也有它的舞台——只要下一场“代码雨”。但别忘了,代码如雨水,需要恰当地“捕捉”和“存储”,否则它们就会悄悄溜走,留下一堆bug的泥泞。