攒青豆 | 青训营 X 码上掘金

61 阅读2分钟

当青训营遇上码上掘金

主题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 单位的青豆。

分析:

该题其实就是力扣中的一个经典例题 “接雨水” ,不过从雨水换成了青豆(还挺应景的)

解法:

动态规划

原理:

  1. 初始化
  • 用ar[i]表示下标为i的元素值

  • 用数组dpl[i] 记录下标为i的元素其左侧最大值。

  • 用数组dpr[i] 记录下标为i的元素其右侧最大值。

    以上三个数组的容量应比原数组大2,即最左侧与最右侧元素设为高度为0的值,以便于后续边界处理。

  1. 第一次遍历(从左至右)
  • 此次遍历记录每个元素其左侧最大元素的值:
  • 因为左侧元素的左侧最大元素值已记录在左侧元素的“备忘录”中,故仅需取该值与左侧元素值中的最大值即可。

伪代码如下:

dpl[i] =max(dpl[i-1] ,ar[i-1])

3. 第二次遍历(从右至左)

类似于第一次遍历

dpr[i] = max(dpr[i+1] ,ar[i+1])

4. 第三次遍历(从左至右)

此次遍历开始记录青豆数量

设x为该元素对应的青豆数量,sum为青豆总数, 伪代码如下:

x=min(dpl[i] ,dpr[i]) - ar[i]

若x小于0(即左右侧都比该位置的值更小)则将x置0

计算完此处的x值后,记录该位置青豆数量: sum+=x

以下为实际代码(golang)