当青训营遇上码上掘金
本文分享「青训营 X 码上掘金」活动中主题4-攒青豆的双指针法,通过Go语言实现。
由于需要从头到尾遍历数组所以时间复杂度O(N) 。
没有额外开辟空间空间复杂度O(1)。
核心思路:只要找到一种方法能解出每个格子所能储存的青豆数量,再把所有格子储存的青豆数加起来就可以了。
而每个格子可以储存青豆的数量只和当前格子左边最高格的高度与右边最高格的高度以及自身高度有关。
即总储存青豆的数量=min(左边最高的格子,右边最高的格子) - 自身的高度
由于需要比较数据大小先实现一个max函数返回两数中最大的,代码如下:
func max(x, y int) int {
if x > y {
return x
}
return y
}
主要变量有四个分别是 l(left) , r(right) , lm(leftMax) , rm(rightMax)
l从下标0开始记录当前左指针位置每次右移++。
r从下标n-1开始记录当前右指针位置每次左移--。
lm记录当前l左边最高格子的高度。
rm记录当前r右边最高格子的高度。
每次 l 右移时比较 l 和 lm , 记录最大值到 lm 中; rm 中同理记录右边最大值。
func Solution(height []int) int {
ans := 0
if len(height) == 0 {
return ans
}
l := 0 //左指针
r := len(height) - 1 //右指针
lm := 0 //左边最高值
rm := 0 //右边最高值
for l < r {
lm = max(lm, height[l]) //更新左边最高值
rm = max(rm, height[r]) //更新右边最高值
由于每个格子所能储存的青豆数量只和lm,rm中最小的有关,所以每次的结果为左右最高值中小的减去当前高度,每次累加结果得到最终答案ans返回。
if lm < rm { //储量只和最小的有关
ans += lm - height[l]
l++
} else {
ans += rm - height[r]
r--
}
}
return ans
}