440 字
2 分钟
42. 接雨水

42. 接雨水#

题目链接: LeetCode 42

题目描述#

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

示例 1:

输入:height = [0,1,0,2,1,0,1,3,2,1,2,1]
输出:6
解释:上面是由数组表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分)。

示例 2:

输入:height = [4,2,0,3,2,5]
输出:9

解题思路#

核心思想#

每个位置能接的水量 = min(左侧最高柱, 右侧最高柱) - height[i](若为正才接水)。用双指针:left、right 从两端向中间靠拢。关键在于:当 height[left] < height[right] 时,位置 left 的水量由左侧最高决定(此时右边界已经足够高),因此我们可以放心处理左指针。

算法步骤#

  1. left=0, right=n-1, left_max=right_max=0, ans=0。
  2. 更新 left_max = max(left_max, height[left])、right_max = max(right_max, height[right])。
  3. 若 height[left] < height[right]:说明 left 处左边界是短板,ans += left_max - height[left],left += 1。
  4. 否则:处理右侧,ans += right_max - height[right],right -= 1。
  5. 重复直到 left >= right,返回 ans。

逐步举例#

height = [0,1,0,2,1,0,1,3,2,1,2,1]:

步骤leftright处理边left_maxright_max增量ans
1011左(0<1)0100
2111左(1<1)→右1101
3110左(1<2)121-1=01
4210左(0<2)121-0=12
…………………6

最终 ans = 6。

复杂度分析#

  • 时间复杂度:O(n),双指针各扫描一次。
  • 空间复杂度:O(1)。

代码实现#

from typing import List
class Solution:
def trap(self, height: List[int]) -> int:
left, right = 0, len(height) - 1
left_max = right_max = 0
ans = 0
while left < right:
left_max = max(left_max, height[left])
right_max = max(right_max, height[right])
if height[left] < height[right]:
ans += left_max - height[left]
left += 1
else:
ans += right_max - height[right]
right -= 1
return ans
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent))
import unittest
from solution import Solution
class TestSolution(unittest.TestCase):
def test_basic(self):
self.assertEqual(Solution().trap([0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1]), 6)
def test_flat(self):
self.assertEqual(Solution().trap([0, 0, 0, 0]), 0)
def test_high_middle(self):
self.assertEqual(Solution().trap([4, 2, 0, 3, 2, 5]), 9)
if __name__ == '__main__':
unittest.main()
42. 接雨水
https://h1s97x.github.io/posts/coding/coding-42-trapping-rain-water/
作者
H1S97X
发布于
2026-08-23
许可协议
CC BY-NC-SA 4.0
随机文章