当青训营遇上码上掘金
题目
现有 n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)
思路
看到题目一下子想到的就是从左往右一个坑一个坑把坑找出来再减去上凸部分。 每个坑只有两种情况,左短右长,或者左长右短。当该柱右侧没有比它更长的,那么它与第二长的形成一个坑,如果遇到比它长的,则直接与其形成一个坑(中间至少隔一个短柱)。
代码实现
height := [...]int{5, 0}
left := 0
right := 1
sum := 0
for ; right < len(height); right++ {
if height[right] > height[left] {
left++
}
if height[right] < height[left] {
for j := right; j < len(height); j++ {
if height[j] > height[right] {
if height[j] > height[left] {
right = j
for k := left + 1; k < right; k++ {
sum = sum + height[left] - height[j]
}
left = height[right]
break
}
right = j
}
}
if height[right] < height[left] {
for k := left + 1; k < right; k++ {
sum = sum + height[right] - height[k]
}
}
left = right
}
}
fmt.Print(sum)
- 先设定最左侧为第一个坑的左侧,向右寻找坑的右侧,如果遇到第一个就比左侧高则将其做为新的坑的左侧再开始向右寻找
right := 1
sum := 0
for ; right < len(height); right++ {
if height[right] > height[left] {
left++
}
}
- 向右比较如遇到当前柱比坑左侧柱高则可以直接确定并完成一个坑的计算,然后令该坑右侧为新坑左侧开始下一坑的计算。
if height[right] < height[left] {
for j := right; j < len(height); j++ {
if height[j] > height[right] {
if height[j] > height[left] {
right = j
for k := left + 1; k < right; k++ {
sum = sum + height[left] - height[j]
}
left = height[right]
break
}
right = j
}
}
3.如果遍历完成都未遇见更高的柱子,则可基本确定坑为左长右短型的,根据遍历时获得的最大值进行计算并开始下一个坑的计算
for k := left + 1; k < right; k++ {
sum = sum + height[right] - height[k]
}
}
left = right
4.最后从左至右走完得到结果