当青训营遇上码上掘金
回顾一下题目要求
-
攒青豆
现有 n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)
ght = [5,0,2,1,4,0,1,0,3]
输出:17
解析:上面是由数组 [5,0,2,1,4,0,1,0,3] 表示的柱子高度,在这种情况下,可以接 17 个单位的青豆。
话不多说,先上题解
const trap = function(height){
let ans = 0;
let left = 0, right = height.length - 1;
let leftMax = 0, rightMax = 0;
while (left <= right){
leftMax = Math.max(leftMax, height[left]);
rightMax = Math.max(rightMax, height[right]);
if (height[left] < height[right]) {
ans += leftMax - height[left];
++left;
} else {
ans += rightMax - height[right];
--right;
}
}
return ans;
};
看起来一通让人似懂非懂的操作,就算出了正确的青豆数
这段代码由于太过对称,所以小白我就当即背下了题解
但是为了感受到这段代码的妙,咱们还是从头推演一遍吧
let ans = 0;
let left = 0, right = height.length - 1
首先这段没什么好说的,准备左指针和右指针,那必然是向中遍历了
let leftMax = 0, rightMax = 0;
while (left < right) {
leftMax = Math.max(leftMax, height[left]);
rightMax = Math.max(rightMax, height[right]);
....
}
这里用上了两个变量,我们尝试理解这两个变量的意义
leftMax = Math.max(leftMax, height[left]);
首先height[left]即为当前左指针遍历到的柱子高度
这一行代码里我们不断更新 left 指针左侧的最高柱子leftMax
同理, rightMax即为 right 指针右侧的最高柱子
while (left < right) {
......
if (height[left] < height[right]){
ans += leftMax - height[left];
++left;
} else {
ans += rightMax - height[right];
--right;
}
}
重点来了,我们为什么需要最高的柱子呢?当然是为了计算青豆的体积,重点在于,我们只计算当前指针这一列的青豆体积,它只与当前列的高度,与左右两侧最大柱子高度有关
比如说
0
0 0
0 0 0 0
1 2 3 4
二号柱上能放多少体积青豆呢?
显然是1体积
0
0 X 0
0 0 0 0
1 2 3 4
已知leftMax为一号柱的高度2
那么二号柱的青豆可以表示为 一号柱的高度减去二号柱的高度
leftMax - height[left]
那么问题来了,如果右边柱子高度不够,该怎么办呢?
0 X
0 0 0 0
1 2 3 4
我们通过这个if判断来保证
if (height[left] <=height[right]){
...
}
右指针保证了右边存在高于当前柱子高度的柱子
那么问题来了,这也是右边存在高于二号柱的情况,
可是这一眼看上去就不合法了啊?
0 X
0 X 0
0 0 0 0
1 2 3 4
这种情况并不会发生,因为我们永远只从安全的一侧出发
0
0 0
0 0 0 0
1 2 3 4
一开始我们发现左指针一号柱高于右指针四号柱
所以在三号柱堆豆子时,由于右侧柱的高度一定小于左侧的某一根柱子,
所以不管怎样,我们用rightMax - height[right]算出的高度一定不会超过左侧柱子高度,
这就是从右往左到达三号柱的理由
即用这个else条件来保证
if (height[left] <=height[right]){
...
}else{
...
--right
}
如果我们发现三号柱比一号柱还高,那我们大可从左边开始,因为左边才是安全的一侧
最终当L=R时,我们退出循环,此时所有列的豆子都已经被计算好了,得到了ans
总之通过if判断,
我们既可以保证当前方向有足够的高度,又能保证左指针和右指针走到哪,哪就是安全的一边
两个判断合二为一,又能完整地遍历一遍数组,妙不可言
算法过于神奇,静下心来理解,慢慢积累!