给定 n
个非负整数表示每个宽度为 1
的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
分析思路
-
指针的移动策略:
- 通过两个指针
left
和right
从数组两侧向中间移动。 left_max
和right_max
分别表示左侧和右侧的最大高度。
- 通过两个指针
-
雨水的积累:
- 首先初始化
left
和right
为数组两端,初始化left_max
和right_max
为 0。 - 在每一步迭代中,比较
left_max
和right_max
,选择较小的那个作为当前高度的最大高度。 - 如果
left_max
小于right_max
,说明左侧的最大高度小于右侧,此时可以计算左侧的雨水,并将left
指针向右移动。 - 如果
right_max
小于等于left_max
,说明右侧的最大高度小于等于左侧,此时可以计算右侧的雨水,并将right
指针向左移动。
- 首先初始化
-
雨水的计算:
- 在每一步迭代中,通过比较
left_max
和right_max
的较小值,可以确定当前位置的最大高度。 - 如果当前位置的高度小于最大高度,说明可以积累雨水,将积累的雨水量累加到
result
中。
- 在每一步迭代中,通过比较
-
迭代的结束条件:
- 当
left
和right
相遇时,迭代结束。
- 当
-
时间复杂度:
- 由于只需要一次遍历数组,时间复杂度是 O(n),其中 n 是数组的长度。
-
空间复杂度:
- 除了常数个变量外,没有使用额外的空间,空间复杂度是 O(1)。
代码实现:
class Solution(object):
def trap(self, height):
"""
:type height: List[int]
:rtype: int
"""
if not height or len(height) < 3:
return 0
left, right = 0, len(height) - 1
left_max, right_max = 0, 0
result = 0
while left < right:
# 更新左侧最大高度
left_max = max(left_max, height[left])
# 更新右侧最大高度
right_max = max(right_max, height[right])
if left_max < right_max:
# 如果左侧最大高度小于右侧,计算左侧的雨水并将左指针向右移动
result += left_max - height[left]
left += 1
else:
# 如果右侧最大高度小于等于左侧,计算右侧的雨水并将右指针向左移动
result += right_max - height[right]
right -= 1
return result
运行实例:
# 示例
height1 = [0,1,0,2,1,0,1,3,2,1,2,1]
height2 = [4,2,0,3,2,5]
solution = Solution()
print(solution.trap(height1)) # 输出:6
print(solution.trap(height2)) # 输出:9