给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
示例 1:
输入: height = [0,1,0,2,1,0,1,3,2,1,2,1]
输出: 6
解释: 上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。
示例 2:
输入: height = [4,2,0,3,2,5]
输出: 9
题解1:动态规划
牢记柱子能装多少水,取决于它左边的最高柱子和右边的最高柱子。
对于任意位置 i 的柱子:
- 如果左边最高比右边最高矮,那么水只能存到左边的高度。
- 如果右边最高比左边最高矮,那么水只能存到右边的高度。
var trap = function(height) {
const n=height.length
if(n===0) return 0
const leftMax=new Array(n).fill(0)
const rightMax=new Array(n).fill(0)
for(let i=1;i<n;i++){
leftMax=Math.max(leftMax[i-1],height[i])
}
for(let i=n-2;i>=0;i--){
rightMax=Math.max(rightMax[i+1],height[i])
}
//开始计算储水量
let water=0
for(let i=0;i<n;i++){
water+=Math.min(leftMax,rightMax)-height[i]
}
return water
}
题解2:双指针——“谁矮移谁,算水靠矮边”
思路
- 用两个指针
left和right,从两端向中间移动 - 用
leftMax和rightMax记录左右最高柱子 - 每次移动高度较小的那一边,因为较小的一边能确定水量
var trap = function(height) {
let water=0
let left=0,right=height-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]){
water+=leftMax-height[left]
left++
} else {
water+=rightMax-height[right]
right--
}
return water
}