文章目录
题目


代码
核心是短板原理:
接的雨水 = min(maxLeft, maxRight) - heighti
但要怎么体现在代码里呢?一开始想的是Math.min(),但学习的时候发现题解里min的影都没见到,而是对比height[left]和height[right]就可以实现对maxLeft和maxRight的对比。解释如下(来自d老师):
当你确定某一边是短板时,你就能断定:这一侧当前的 Max(最大值)一定就是全局的 min。
我们分情况证明(以左边为例):
当height[left] < height[right]成立时(左边是短板):
- 因为
rightMax >= height[right](右侧最大值至少是当前这根右柱子),所以rightMax > height[left]。 - 关键来了:此时
leftMax必然小于或等于rightMax。
为什么?用反证法------如果左边的最大值(leftMax)比右边的最大值(rightMax)还大,说明左边有一堵"超级高墙"。按照"移动短板"的规则,当指针还停留在那堵超级高墙时,因为它比右边的所有墙都高,算法会一直移动右指针向左靠拢,直到左右指针相遇,游戏结束------左指针压根儿没机会走到现在这个位置。
既然左指针走到了这里,就说明左边不存在比右边整体更高的墙,所以leftMax <= rightMax。
js
/**
* @param {number[]} height
* @return {number}
*/
var trap = function(height) {
// 接的雨水 = min(maxLeft, maxRight) - height[i]
let maxLeft = 0, maxRight = 0;
let left = 0, right = height.length - 1;
let res = 0;
while (left < right) {
if (height[left] < height[right]) {
maxLeft = Math.max(height[left], maxLeft);
res += maxLeft - height[left];
left++;
} else {
maxRight = Math.max(height[right], maxRight);
res += maxRight - height[right];
right--;
}
}
return res;
};