当青训营遇上码上掘金

60 阅读2分钟

当青训营遇上码上掘金

题目

主题 4:攒青豆

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

思路

使用双指针的方法 定义两个数,分别代表左右指针,分别对应左边和右边的数据,初始值分别为0和数组的长度减1 初始化两个值,分别对应左边和右边的最大值。

左右指针向中间移动。左指针是左边柱子最大高度,右指针是右边柱子最大高度。当左指针小于右指针时,左指针右移;当左指针大于等于右指针时,右指针左移。
时间复杂度:O(N)。
空间复杂度:O(1)。 通过左右最大值进行累加,只要right_max[i]>left_max[i],积水高度将由 left_max 决定;同理right_max[i]<left_max[i],青豆高度将由 right_max 决定。

微信图片_20230212172648.jpg

注意事项

在做题的过程中遇到了两个错误,给大家分享一下(我是小白):

1、go语言中没有while关键字,不支持while和do-while循环结构。从功能上讲,但凡while语句能做的事情,for语句也可以实现,因此Go语言统一了for语句和while语句. while循环可通过for循环实现。

image.png

2、运行这样的代码会报错

package main

import (
    "fmt"
)

b := 1

func main() {
    fmt.Println(b)
}

原因在于 := 只能用于方法内,当定义全局变量时只能通过 var 关键字来定义

代码实现

package main
import "fmt"
func main() {
  //输入数组
    height := []int{4,2,0,3,2,5}
    //计算青豆数量
    var ret = trap(height)
    //打印出结果
    fmt.Println(ret)
}

func trap(height []int) int {
        left:=0
        right := len(height)-1
        //初始化结果值
        var ans = 0
        left_max:=0
        right_max:=0
        //进行循环
        //退出条件是左指针大于等于右指针
        for{
        if(left < right){
            //只要right_max[i]>left_max[i],青豆高度将由 left_max 决定
            if(height[left] < height[right]){//这时候最大值在left这边
                //当当前位置的值大于之前的最大值,是不能进行累加的
                if(height[left] >= left_max){
                    //所以需要将最大值进行替换为当前位置的值
                    left_max = height[left];
                }else{//当前位置的值小于之前的最大值,是可以累加的
                    //按列进行相加,最大值减去当前位置的高度即为所求
                    ans += (left_max - height[left]);
                }
                //向右移动
                left++;
            }else{//这时候最大值在右边
                if(height[right] >= right_max){
                    right_max = height[right];
                }else{
                    ans += (right_max-height[right]);
                }
                //向左移动
                right--;
            }
        }else{ 
                        break}

    }
        return ans
}