LeetCode 接雨水问题解析与 Python 实现

接雨水(Trapping Rain Water)问题是一个经典的算法问题,通常出现在编程面试和在线评测中。问题描述如下:给定一个非负整数数组 height,其中 height[i] 表示在位置 i 处的高度。计算在这些柱子之间可以接住多少雨水。

问题分析

接雨水的核心思想是,对于每一个位置 i,我们需要找到左右两边的最高柱子(left_max 和 right_max),雨水的量等于 min(left_max, right_max) - height[i]。不过,仅靠基础的循环实现,时间复杂度为 O(n^2),这对于较大的输入是不可接受的。

因此,我们通常采用双指针的方法。具体步骤如下:

  1. 初始化两个指针,left 指向数组的开始,right 指向数组的结束。
  2. 用两个变量 left_maxright_max 分别存储 leftright 指向的柱子的最大高度。
  3. 迭代直到 leftright 相遇,根据 left_maxright_max 计算接水量。

代码实现

以下是使用 Python 实现接雨水问题的代码:

def trap(height):
    if not height:
        return 0

    left, right = 0, len(height) - 1
    left_max, right_max = height[left], height[right]
    water_trapped = 0

    while left < right:
        if height[left] < height[right]:
            left += 1
            left_max = max(left_max, height[left])
            water_trapped += left_max - height[left]
        else:
            right -= 1
            right_max = max(right_max, height[right])
            water_trapped += right_max - height[right]

    return water_trapped

复杂度分析

  • 时间复杂度: O(n),因为每个柱子仅被访问一次。
  • 空间复杂度: O(1),仅使用了常数空间来存储变量。

甘特图表示时间复杂度分析

通过甘特图,我们可以清晰地查看算法的执行时间。

gantt
    title 接雨水算法时间复杂度分析
    dateFormat  YYYY-MM-DD
    section 遍历柱子
    初始化指针         :a1, 2023-10-01, 1d
    更新最大高度       :after a1  , 2d
    计算接雨量         :after a1  , 3d

序列图

通过序列图,我们可以更好地理解每个步骤的执行顺序:

sequenceDiagram
    participant U as 用户
    participant F as 函数
    U->>F: trap(height)调用
    F->>F: 初始化指针和最大高度
    F->>F: 进入while循环
    alt height[left] < height[right]
        F->>F: 更新left指针
        F->>F: 更新left_max
        F->>F: 计算接水量
    else height[left] >= height[right]
        F->>F: 更新right指针
        F->>F: 更新right_max
        F->>F: 计算接水量
    end
    F->>U: 返回接水量

结尾

接雨水问题不仅是算法和数据结构的一个有趣案例,更是面试中的常见考题。通过合理地分析和利用双指针方法,我们可以有效地解决问题。希望本文的探讨能为大家在解题过程中提供思路与启发。学习编程的过程中,编写和理解这些算法能帮助我们更好地应对面试及实际问题。