当青训营遇上码上掘金之攒青豆(Go)

92 阅读2分钟

当青训营遇上码上掘金

码上掘金

题目:

现有 n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积) image.png 输入:height = [5,0,2,1,4,0,1,0,3] 

输出:17 

解析:上面是由数组 [5,0,2,1,4,0,1,0,3] 表示的柱子高度,在这种情况下,可以接 17 个单位的青豆。


思路:

柱面height[]从第一个height[0]开始,直到下一个最大高度height[i]的柱面,青豆数目就是在这两个之间数出来,接下来就是分析这个柱面怎么产生的。(青训营给的示例是剩余的柱面高度都是小于第一个的,但为了全面点,应该考虑柱面大于的情况。)

下一个柱面height[i],应是除了第一个柱面外最高的。接着讨论:如果柱面高度height[i]>第一个柱面高度height[0],那么选择的基准水平面就是height[0];反之选择height[i]高度为基准水平面。即在两个最高的柱面间选择较低的。

然后以此类推,以height【】为新的height【0】,接着找下一个最大高度height【】,直到最后一个柱面结束。

总的要点:1找到最高柱面的位置;2计算两个柱面间的青豆数,直到最后的柱面

第一点是一个查找,找最大值;第二点是一个简单的计算,且是持续向后叠加的过程,只需遍历一次原数组,Go的切片比数组灵活性大,且可以通过切片表达式,实现逻辑;切片是引用类型,复用切片底层数组不变。

代码如下

package main

import (
	"fmt"
)

func maxloc(a []int)int{
        flag:=a[1]
        loc:=int(0)
        for i:=0;i<len(a);i++{
                if(flag<a[i]){
                        flag=a[i]
                        loc=i
                }
        }
        return loc
}

func main(){
        var height=make([]int,0,10)
        height=append(height,5,0,2,1,4,0,1,0,3)
        loc:=maxloc(height)
        sum:=0
        for {
                for i:=0;i<loc;i++{
                sum+=height[loc]-height[i]
                }
                if len(height)!=loc+1{
                height=height[loc+1:]
                loc=maxloc(height)
                }else{ break}
        }
        fmt.Printf("青豆的总数是:%d",sum)
}

源地址:当青训营遇上码上掘金之攒青豆 - 码上掘金 (juejin.cn)