以前看面试题的时候,看到了一个接雨水的问题,和小黄鸭讨论以后,以为颇有趣呢,这里和你们分享一下这个解法。后来看到LeetCode上面有这道题,题号42,有兴趣的能够作一下。面试
给定n个非负整数表示每一个宽度为1的柱子的高度图,计算彼此排列的柱子,下雨以后能接多少雨水。数组
示例1:markdown
输入:height = [0,1,0,2,1,0,1,3,2,1,2,1]
输出:6优化
实例2:ui
输入:height = [4,2,0,3,2,5]
输出:9spa
你能不能先思考一下,遇到这种问题,你要怎么作呢?3d
首先咱们能够根据给的数组,先画出来柱子的长度。code
那么咱们怎么肯定接的雨水的量呢?固然是两个都高中间低的地方,来存储水,下面阴影的部分就是储存水的位置。orm
那么咱们须要对左边和右边最高水位作一个统计,这边使用到了两个辅助数组图片
一个用来储存左边的最大接雨水数,一个存储右边的最大接雨水数。
选择两个中最小的那个做为存储水的量
固然还要减去本身柱子的高度。剩下的,就是能够接的雨水了。
function trap(height) {
if(!height.length) return 0;
let left = []
let right = []
let lmax = rmax = 0
let len = height.length
let result = 0
// 把左右最大出水量求出来
for(let i = 0; i < len; i++) {
lmax = Math.max(height[i], lmax)
rmax = Math.max(height[len-i-1], rmax)
left[i] = lmax
right[len- i - 1] = rmax
}
// 算出最小的而后累加
for(let i = 0; i < len; i++) {
result += Math.min(left[i],right[i]) - height[i]
}
return result
};
复制代码
若是想要写法上优化一下,能够第二次遍历的时候可使用reduce
function trap(height) {
if(!height.length) return 0;
let left = []
let right = []
let lmax = rmax = 0
let len = height.length
for(let i = 0; i < len; i++) {
lmax = Math.max(height[i], lmax)
rmax = Math.max(height[len-i-1], rmax)
left[i] = lmax
right[len- i - 1] = rmax
}
return height.reduce((prev, item, index) => {
return prev + Math.min(left[index],right[index]) - item
}, 0)
};
复制代码
其实右边数组的值的存储是能够省略的,虽然都是空间复杂度O(n),可是也算小小的优化点。
function trap(height) {
if(!height.length) return 0;
let left = []
let lmax = rmax = 0
let len = height.length
let result = 0
for(let i = 0; i < len; i++) {
lmax = Math.max(height[i], lmax)
left[i] = lmax
}
// 从后往前遍历
for(let i = len - 1; i >= 0; i--) {
rmax = Math.max(height[i], rmax)
result += Math.min(left[i],rmax) - height[i]
}
return result
};
复制代码