返回

LeetCode 42:雨水截存——下雨天,房子屋顶如何蓄水?

前端

LeetCode 42:雨水截存

这是一道经典的动态规划题目,也是 LeetCode 的热门题目之一。题目要求我们计算在一个给定的数组中,有多少个元素可以截存雨水。

我们可以将数组中的每个元素看成一个柱子,那么雨水截存的问题就转化为:在这些柱子中,有多少个柱子可以截存雨水?

为了解决这个问题,我们可以使用动态规划的方法。首先,我们需要计算出每个柱子的最大左边柱子和最大右边柱子。然后,我们就可以计算出每个柱子可以截存的雨水量。最后,我们只需要将所有柱子的雨水量加起来,就得到了总的雨水截存量。

除了动态规划的方法之外,我们还可以使用滑动窗口的方法来解决这个问题。滑动窗口的方法是一种贪心算法,它通过移动一个窗口来计算每个柱子可以截存的雨水量。滑动窗口的方法比动态规划的方法简单,但它可能会导致错误的结果。

下面,我们分别介绍动态规划和滑动窗口两种方法的具体实现。

动态规划方法

def trap(height):
    """
    计算一个数组中可以截存的雨水量。

    参数:
        height:一个数组,表示柱子的高度。

    返回值:
        一个整数,表示总的雨水截存量。
    """

    # 初始化动态规划数组
    dp = [0] * len(height)

    # 计算每个柱子的最大左边柱子和最大右边柱子
    max_left = [0] * len(height)
    max_right = [0] * len(height)
    max_left[0] = height[0]
    max_right[-1] = height[-1]
    for i in range(1, len(height)):
        max_left[i] = max(max_left[i-1], height[i])
    for i in range(len(height)-2, -1, -1):
        max_right[i] = max(max_right[i+1], height[i])

    # 计算每个柱子可以截存的雨水量
    for i in range(1, len(height)-1):
        dp[i] = min(max_left[i], max_right[i]) - height[i]

    # 计算总的雨水截存量
    return sum(dp)

滑动窗口方法

def trap(height):
    """
    计算一个数组中可以截存的雨水量。

    参数:
        height:一个数组,表示柱子的高度。

    返回值:
        一个整数,表示总的雨水截存量。
    """

    # 初始化滑动窗口
    left = 0
    right = len(height) - 1
    max_left = 0
    max_right = 0
    total = 0

    # 移动滑动窗口
    while left < right:
        # 计算左边柱子的最大值
        if height[left] < height[right]:
            if height[left] > max_left:
                max_left = height[left]
            total += max_left - height[left]
            left += 1
        # 计算右边柱子的最大值
        else:
            if height[right] > max_right:
                max_right = height[right]
            total += max_right - height[right]
            right -= 1

    return total

结语

动态规划和滑动窗口两种方法都是解决LeetCode 42题:雨水截存的有效方法。动态规划的方法更加准确,但复杂度更高;滑动窗口的方法更加简单,但可能会导致错误的结果。在实际应用中,我们可以根据具体情况选择合适的方法。