返回

从LeetCode 掘金酱打卡挑战学习动态规划:妙用双指针计算雨水量

闲谈

动态规划的魅力

动态规划是一种解决复杂问题的经典算法范式。其基本思想是将问题分解成一系列子问题,依次求解每个子问题,并将子问题的解存储起来,以便在求解后续子问题时复用。这种方法可以大大提高算法的效率,尤其适用于具有重叠子问题的场景。

双指针的妙用

双指针是一种简洁高效的算法技巧,常用于解决数组或链表等线性数据结构相关的问题。其基本思想是在数据结构的两端设置两个指针,然后以一定的方式移动这些指针,同时对数据结构进行操作。双指针算法通常可以将复杂度降低至线性和对数级别,显著提升算法效率。

问题建模与算法设计

雨水量计算问题可以抽象为一个柱状图模型。给定 n 个非负整数表示每个柱子的高度,我们需要计算当雨水落下时,柱状图中能接住多少雨水。为了解决这个问题,我们可以使用动态规划和双指针算法。

  1. 动态规划:

    我们将问题分解成若干子问题,每个子问题对应柱状图中某一段连续的柱子。对于每个子问题,我们可以计算出该段柱子所能接住的雨水量。然后,我们将这些子问题的解累加起来,即可得到整个柱状图的雨水量。

  2. 双指针:

    为了高效地求解子问题,我们可以使用双指针算法。我们从柱状图的两端分别设置两个指针,然后以一定的方式移动这些指针,同时计算子问题的解。这种方法可以将复杂度降低至线性和对数级别,显著提升算法效率。

代码示例

def trap(height):
    """
    计算柱状图中能接住的雨水量

    Args:
        height (list): 柱状图每个柱子的高度

    Returns:
        int: 雨水量
    """

    # 使用双指针
    left, right = 0, len(height) - 1

    # 初始化左右两侧的最大高度
    left_max, right_max = height[left], height[right]

    # 累计雨水量
    total_water = 0

    # 当左右指针未相遇时
    while left < right:

        # 如果左指针指向的柱子高度较低
        if left_max < right_max:

            # 移动左指针并更新最大高度
            left += 1
            left_max = max(left_max, height[left])

            # 计算当前柱子能接住的雨水量
            total_water += left_max - height[left]

        # 否则右指针指向的柱子高度较低
        else:

            # 移动右指针并更新最大高度
            right -= 1
            right_max = max(right_max, height[right])

            # 计算当前柱子能接住的雨水量
            total_water += right_max - height[right]

    # 返回累计雨水量
    return total_water

结语

通过LeetCode 掘金酱打卡挑战,我们学习了如何运用动态规划和双指针算法解决雨水量计算问题。这种方法不仅可以帮助我们理解动态规划和双指针算法的原理,而且可以为我们解决其他类似问题提供思路。希望本文能帮助您提升算法技能,在面试和程序设计中取得优异成绩。