接雨水问题
问题背景
LeetCode 42. 接雨水
接雨水问题是一个经典的计算雨水滞留量的问题,通常使用柱状图来表示不同高度的柱子。在下雨的情况下,柱子之间的凹陷部分能够存储雨水,问题的目标是计算这些柱子所能接收的雨水总量。
相关知识
在解决接雨水问题之前,需要了解以下几个关键概念:
- 柱状图:表示不同高度的柱子,通常由一个整数数组表示,每个元素代表柱子的高度。
- 雨水滞留:在柱状图中,两根柱子之间的凹陷部分可以存储雨水,我们需要计算这些凹陷部分的总容量。
问题介绍
给定一个由非负整数表示的柱状图,每个柱子的宽度为 1,计算这个柱状图可以接收多少雨水。
问题示例
示例 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 个单位的雨水(蓝色部分表示雨水)。
示例 2:
输入:height = [4,2,0,3,2,5]
输出:9
解题思路
接雨水问题的解决思路通常使用双指针法。具体步骤如下:
- 初始化左指针
left
和右指针right
,并初始化左侧最大高度leftMax
和右侧最大高度rightMax
为 0。 - 使用
left
和right
指针从两端向中间遍历柱子,每次比较left
和right
指针所指的柱子高度,并更新左侧最大高度leftMax
和右侧最大高度rightMax
。 - 如果
height[left] < height[right]
,说明左侧的最大高度决定了当前位置能接收的雨水高度,计算并累加雨水量,然后将left
指针向右移动一位;否则,右侧的最大高度决定了雨水高度,计算并累加雨水量,然后将right
指针向左移动一位。 - 重复步骤 2 和步骤 3,直到
left
和right
指针相遇。
最终,累加的雨水量即为所求的雨水滞留量。
代码实现
class Solution:
def trap(self, height: List[int]) -> int:
# 初始化结果为0
res = 0
# 初始化左指针left和右指针right
left, right = 0, len(height) - 1
# 初始化左侧最大高度leftMax和右侧最大高度rightMax
leftMax = rightMax = 0
# 当左指针小于右指针时,继续循环
while left < right:
# 更新左侧最大高度leftMax
leftMax = max(leftMax, height[left])
# 更新右侧最大高度rightMax
rightMax = max(rightMax, height[right])
# 如果左侧当前高度小于右侧当前高度
if height[left] < height[right]:
# 计算当前位置能接的雨水量并累加到结果中
res += leftMax - height[left]
# 移动左指针向右移动一位
left += 1
else:
# 否则,计算当前位置能接的雨水量并累加到结果中
res += rightMax - height[right]
# 移动右指针向左移动一位
right -= 1
# 返回最终结果
return res
上述 Python 代码实现了双指针法的思路。首先,我们初始化左指针 left
和右指针 right
,以及左侧最大高度 leftMax
和右侧最大高度 rightMax
。然后,使用指针从两端向中间遍历柱子,计算并累加雨水量。最后,返回累加的雨水量作为结果。
时间和空间复杂度
- 时间复杂度:双指针法的时间复杂度为 O(n),其中 n 是柱子的数量。
- 空间复杂度:双指针法只需要常数级别的额外空间,空间复杂度为 O(1)。
结论
接雨水问题是一个经典的算法问题,通过双指针法,我们可以高效地计算雨水滞留量。