当青训营遇上码上掘金
主题创作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 个单位的青豆。
思路:
可以使用动态规划
进行预处理,创建长度为的两个数组和,分别记录下标位置和左边位置的Height的最大高度,则表示和右边位置的Height的最大高度。为,为。
各个位置的和的取值如下:
之后分别进行正向遍历和反向遍历Height数组,处能接到的最大青豆数量为,对每个位置进行遍历求和得到总量,算法的复杂度为
代码:
环境:码上掘金
语言:Go
package main
import "fmt"
func getAns(hs []int) (ans int) {
//获取数组长度赋值为n
n := len(hs)
//判断n是否为0,是则直接返回
if n == 0{
return
}
//l为记录左半部分最大值的数组,长度为n
l := make([]int, n)
l[0] = hs[0]
//l[i]为数组求最值
for i := 1; i < n; i++ {
l[i] = max(hs[i],l[i-1])
}
//r为记录右半部分最大值的数组,长度为n
r := make([]int, n)
r[n-1] = hs[n-1]
for i := n - 2; i >= 0; i-- {
r[i] = max(hs[i],r[i+1])
}
//遍历相加
for i, hs := range hs{
ans += min(l[i], r[i]) - hs
}
return
}
//求最小值
func min(a, b int) int {
if a < b{
return a
}
return b
}
//求最大值
func max(a, b int) int {
if a > b{
return a
}
return b
}
func main() {
/*
var hs = []int{5,0,2,1,4,0,1,0,3}
ans := getAns(hs)
fmt.Println("按此排列的柱子能接住的青豆数量为:", ans)
*/
var num int
fmt.Scan(&num)
hs := make([]int, num)
for i := 0; i < num; i++ {
fmt.Scan(&hs[i])
}
ans := getAns(hs)
fmt.Println("按此排列的柱子能接住的青豆数量为:", ans)
}