当青训营遇上码上掘金

62 阅读2分钟

当青训营遇上码上掘金

  • 主题 4:攒青豆

    现有 n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)

攒青豆.png

以下为上图例子的解析:

输入:height = [5,0,2,1,4,0,1,0,3]  
输出:17  
解析:上面是由数组 [5,0,2,1,4,0,1,0,3] 表示的柱子高度,在这种情况下,可以接 17 个单位的青豆。

代码

def trap(height):
    n = len(height)
    res = 0
    for i in range(1, n - 1):
        left_max = max(height[:i])
        right_max = max(height[i:])
        res += min(left_max, right_max) - height[i]
    return res

这是一个典型的接雨水问题,可以用双指针法来解决。

从两侧开始向中间移动两个指针,每次移动较矮的柱子所在的指针,并且在移动时更新当前最高的柱子高度。假设左指针所在的柱子高度为 lhl_h,右指针所在的柱子高度为 rhr_h,当前最高柱子高度为 maxhmax_h,则在移动左指针时,可以计算出左指针能接住的青豆数量为 maxhlhmax_h - l_h,在移动右指针时,可以计算出右指针能接住的青豆数量为 maxhrhmax_h - r_h。将两个数量相加即为当前状态下能接住的青豆数量。

具体算法流程如下:

  1. 初始化左右指针和当前最高柱子高度为0。
  2. 当左指针小于右指针时,重复步骤3到步骤5;否则重复步骤6到步骤8。
  3. 如果当前左指针所在的柱子高度小于等于右指针所在的柱子高度,则更新当前最高柱子高度为左指针所在的柱子高度。
  4. 计算左指针能接住的青豆数量,并将结果累加到答案中。
  5. 左指针向右移动一格。
  6. 如果当前右指针所在的柱子高度小于等于左指针所在的柱子高度,则更新当前最高柱子高度为右指针所在的柱子高度。
  7. 计算右指针能接住的青豆数量,并将结果累加到答案中。
  8. 右指针向左移动一格。
  9. 返回答案。