当青训营遇上码上掘金
主题4 攒青豆
首先我们要明确青豆数量所有可利用的容积的和。 我们要按照每一列求青豆的数量,,我们只需要关注当前列,以及左边最高的墙,右边最高的墙就够了。 装青豆的多少,当然根据木桶效应,我们只需要看左边最高的墙和右边最高的墙中较矮的一个就够了。 所以,根据较矮的那个墙和当前列的墙的高度可以分为三种情况。
- 较矮的墙的高度小于当前列的墙的高度
- 较矮的墙的高度等于当前列的墙的高度。
- 较矮的墙的高度大于于当前列的墙的高度。 只有较矮的墙大于当前的列时才能储存青豆。
双指针
package main
import (
"fmt"
"strconv"
"strings"
)
func trap(height []int) (ans int) {
left, right := 0, len(height)-1
//记录左右两边最高高的墙
leftMax, rightMax := 0, 0
//循环遍历数组
for left < right {
leftMax = max(leftMax, height[left])
rightMax = max(rightMax, height[right])
// 用双指针记录
if height[left] < height[right] {
//height[left] < height[right]说明右侧一定存在比左侧高的墙
// 让左侧减去之前最高的墙
ans += leftMax - height[left]
left++
} else {
ans += rightMax - height[right]
right--
}
}
return
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
func main(){
var l1 string;
fmt.Scanln(&l1)
//序列化输入的内容
str1:=strings.Split(l1[1 : len(l1)-1], ",")
res:=make([]int,len(str1));
// 使字符数组转化为int数组
for i,v:=range str1{
res[i],_=strconv.Atoi(v)
}
fmt.Print(trap(res))
}
动态规划
package main
import (
"fmt"
"strconv"
"strings"
)
func trap(height []int) (ans int) {
n := len(height)
if n == 0 {
return
}
//数组记录每个墙左右最大值
leftMax := make([]int, n)
leftMax[0] = height[0]
for i := 1; i < n; i++ {
leftMax[i] = max(leftMax[i-1], height[i])
}
rightMax := make([]int, n)
rightMax[n-1] = height[n-1]
for i := n - 2; i >= 0; i-- {
rightMax[i] = max(rightMax[i+1], height[i])
}
for i, h := range height {
ans += min(leftMax[i], rightMax[i]) - h
}
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 l1 string;
fmt.Scanln(&l1)
//序列化输入的内容
str1:=strings.Split(l1[1 : len(l1)-1], ",")
res:=make([]int,len(str1));
// 使字符数组转化为int数组
for i,v:=range str1{
res[i],_=strconv.Atoi(v)
}
fmt.Print(trap(res))
}