当青训营遇上码上掘金 这是我参与「 第五届青训营 」的第 3 天,今天参与了「青训营 X 码上掘金」主题创作活动,并使用了码上掘金平台解决了第四题攒青豆并编写了个人题解。
题目描述
现有 n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)
以下为上图例子的解析:
输入:height = [5,0,2,1,4,0,1,0,3]
输出:17
解析:上面是由数组 [5,0,2,1,4,0,1,0,3] 表示的柱子高度,在这种情况下,可以接 17个单位的青豆。
思路
- 能攒下青豆的条件为在一个或若干个元素的两侧存在高度差且呈V字形,例如[5,3,6],[5,2,3,4,6]这样的结构才能够攒下青豆
- 可以先从左侧找到一个最高点,然后再从右侧找到一个最高点,将最高点的数据保存为数组
- 最后结果统计用左侧最高点与右侧最高点取最小值再减去底部高度,所得的值就是这个点所能攒下的最多的青豆的值
解题代码
解析
从左到右找到左侧的最高点 对arr数组进行遍历,将最高点数据保存至l数组,根据题目提供的数据可得从左至右的最高点都是5,没有发生高度的变化,l数组为[5,5,5,5,5,5,5,5,5],若arr[4]=6时,l数组则为[5,5,5,5,6,6,6,6,6]
length := len(arr)
l := make([]int, length)
l[0] = arr[0]
for i := 1; i < length; i++ {
l[i] = int(math.Max(float64(l[i-1]), float64(arr[i])))
}
arr[1] < l[0]l[1] = l[0]
arr[2] < l[1]l[2] = l[1]
arr[3] < l[2]l[3] = l[2]
...
从右到左找到左侧的最高点 对arr数组进行遍历,将最高点数据保存至r数组,原数据中arr[5]大于右测最高点,所以应对数据进行更新,将右测最高点置为4保存到r数组中,可得r数组为[5,4,4,4,4,3,3,3,3]
r := make([]int, length)
r[length-1] = arr[length-1]
for i := length - 2; i >= 0; i-- {
r[i] = int(math.Max(float64(r[i+1]), float64(arr[i])))
}
arr[7] < r[8]r[7] = r[8]
arr[6] < r[7]r[6] = r[7]
arr[5] < r[6]r[5] = r[6]
arr[4] > r[5]r[4] = arr[4]
arr[3] < r[4]r[3] = r[4]
arr[2] < r[3]r[2] = r[3]
arr[1] < r[2]r[1] = r[2]
arr[0] > r[1]r[0] = arr[0]
结果 用左侧最高点与右侧最高点取最小值,所得的最小值为这两点中间所能存放的最多的青豆,再减去底部高度,最终累加结果返回
ans := 0
for i := 0; i < length; i++ {
ans += int(math.Min(float64(l[i]), float64(r[i]))) - arr[i]
}
ans = 4+2+3+3+2+3