当青训营遇上码上掘金
-
主题 4:攒青豆
现有 n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)
以下为上图例子的解析:
输入: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
这是一个典型的接雨水问题,可以用双指针法来解决。
从两侧开始向中间移动两个指针,每次移动较矮的柱子所在的指针,并且在移动时更新当前最高的柱子高度。假设左指针所在的柱子高度为 ,右指针所在的柱子高度为 ,当前最高柱子高度为 ,则在移动左指针时,可以计算出左指针能接住的青豆数量为 ,在移动右指针时,可以计算出右指针能接住的青豆数量为 。将两个数量相加即为当前状态下能接住的青豆数量。
具体算法流程如下:
- 初始化左右指针和当前最高柱子高度为0。
- 当左指针小于右指针时,重复步骤3到步骤5;否则重复步骤6到步骤8。
- 如果当前左指针所在的柱子高度小于等于右指针所在的柱子高度,则更新当前最高柱子高度为左指针所在的柱子高度。
- 计算左指针能接住的青豆数量,并将结果累加到答案中。
- 左指针向右移动一格。
- 如果当前右指针所在的柱子高度小于等于左指针所在的柱子高度,则更新当前最高柱子高度为右指针所在的柱子高度。
- 计算右指针能接住的青豆数量,并将结果累加到答案中。
- 右指针向左移动一格。
- 返回答案。