当青训营遇上码上掘金。
题目
主题 4:攒青豆
现有 n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)
思路
使用双指针的方法 定义两个数,分别代表左右指针,分别对应左边和右边的数据,初始值分别为0和数组的长度减1 初始化两个值,分别对应左边和右边的最大值。
左右指针向中间移动。左指针是左边柱子最大高度,右指针是右边柱子最大高度。当左指针小于右指针时,左指针右移;当左指针大于等于右指针时,右指针左移。
时间复杂度:O(N)。
空间复杂度:O(1)。
通过左右最大值进行累加,只要right_max[i]>left_max[i],积水高度将由 left_max 决定;同理right_max[i]<left_max[i],青豆高度将由 right_max 决定。
注意事项
在做题的过程中遇到了两个错误,给大家分享一下(我是小白):
1、go语言中没有while关键字,不支持while和do-while循环结构。从功能上讲,但凡while语句能做的事情,for语句也可以实现,因此Go语言统一了for语句和while语句. while循环可通过for循环实现。
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
}