双指针
在暴力解法的核心主要是查找出左右两边的最大值,但是我们仔细分析会发现,只要 right_max[i] > left_max[i],柱子i位置的最大存水量就由left_max决定;反之如果 left_max[i] > right_max[i],则由right_max决定。
根据这个思路,我们还是先从左往右扫描数组,我们可以认为如果一侧有更高的柱子(例如右侧),积水的高度依赖于当前方向的高度(从左到右)。当我们发现另一侧(右侧)的条形块高度不是最高的,我们则开始从相反的方向遍历(从右到左)。
此时我们维护左右两个指针,通过两个指针交替进行遍历,实现一次遍历完成。
对于位置left而言,它左边的最大值一定是left_max,右边的最大值大于等于right_max。如果此时left_max < right_max,那么它就能计算出它的位置能存多少水,无论右边将来会不会出现更大的值,都不影响计算出的结果,所以当height[left] < height[right] 时,我们去处理left指针。反之,我们去处理right指针。
var trap = function(height) {
let sum = 0;
let left_max = 0;
let right_max = 0;
let left = 0;
let right = height.length - 1;
while(left < right) {
if (height[left] < height[right]) {
left_max = Math.max(left_max, height[left]);
sum += left_max - height[left];
left++;
} else {
right_max = Math.max(right_max, height[right]);
sum += right_max - height[right];
right--;
}
}
return sum;
};
// 单调栈
var 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;
};
var trap = function(height) {
let ans = 0;
const stack = [];
const n = height.length;
for (let i = 0; i < n; ++i) {
while (stack.length && height[i] > height[stack[stack.length - 1]]) {
const top = stack.pop();
if (!stack.length) {
break;
}
const left = stack[stack.length - 1];
const currWidth = i - left - 1;
const currHeight = Math.min(height[left], height[i]) - height[top];
ans += currWidth * currHeight;
}
stack.push(i);
}
return ans;
};
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/trapping-rain-water/solution/jie-yu-shui-by-leetcode-solution-tuvc/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。