开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第1天,点击查看活动详情
接雨水
leetcode 42题 —— 接雨水
这道题目初次看完题,尝试用暴力解法。发现越解答越难。 重新再阅读一遍题目。分析解法。寻找切入点。
现在假设只考虑某一个柱子的情况。其他都不考虑、比如我们现在来看看示例一给出的数组。
height = [0,1,0,2,1,0,1,3,2,1,2,1]
比如说下标为5的数据。柱子高度为0。从示例图中,可以直观的看到。他的积水量为2。在他左边的柱子最高的高度为2。右边柱子最高的高度为3。那么,我们是否能够。先把每一条数据的左边柱子的最高点和右边柱子的最高点计算出来呢?
- 从左往右看。寻找每个柱子左边最高的柱子的值。如图橙色区域。
通过循环柱子高度。选取每个柱子左边柱子的高度和当前柱子高度的最大值。作为左边柱子最大值。
let arr = []
for(let i=0;i<len;i++){
if(i===0){
arr[i] = height[0]
}else{
arr[i] = Math.max(arr[i-1,height[i])
}
}
- 从右往左看。寻找每个柱子右边最高柱子的坐标值。如图绿色区域。
通过循环柱子高度。选取每个柱子左边柱子的高度和当前柱子高度的最大值。作为右边柱子最大值。
let arr = []
for(let i=0;i<len;i++){
if(i===0){
arr[len-i-1] = height[len-i-1]
}else{
arr[len-i-1] = Math.max(arr[len-i],height[len-i-1])
}
}
这两组代码已经求出来每个柱子左边柱子的最大值和右边柱子的最大值。 接下来,我们把两组值进行优化。放在一个二维数组中。方便后续的对比操作。
const len = height.length
let arr = Array.from({length:len},()=>new Array(2))
for(let i=0;i<len;i++){
if(i===0){
arr[i][0] = height[0]
arr[len-i-1][1] = height[len-i-1]
}else{
arr[i][0] = Math.max(arr[i-1][0],height[i])
arr[len-i-1][1] = Math.max(arr[len-i][1],height[len-i-1])
}
}
这个时候,我们已经求出了一个二维数组。数组中的第0项和第1项分别为左边和右边的柱子最大高度。
就像要给一个木板长度不一拼接成的木桶装水一样。只要招到木桶最短的一块板。就能求出木桶的最大值。
接下来。我们只要在左边最最高的点和右边最高的点找出其中最小项。再和当前柱子自身的高度做对比。就能求出当前坐标下。可以收集到的雨水。上代码。
var trap = function(height) {
const len = height.length
let arr = Array.from({length:len},()=>new Array(2))
for(let i=0;i<len;i++){
if(i===0){
arr[i][0] = height[0]
arr[len-i-1][1] = height[len-i-1]
}else{
arr[i][0] = Math.max(arr[i-1][0],height[i])
arr[len-i-1][1] = Math.max(arr[len-i][1],height[len-i-1])
}
}
let sum = 0
for(let i=0;i<len;i++){
const dis = Math.min(arr[i][0],arr[i][1])
if(dis>height[i]){
sum = sum+dis-height[i]
}
}
return sum
};
复杂度
时间复杂度:O(n)O(n),其中 n 是数组height 的长度。计算数组左右最高柱子的值。需要遍历数组 height 一次,计算能接的雨水总量还需要遍历一次。
空间复杂度:O(n)O(n),其中 n 是数组 height 的长度。需要创建两个长度为 nn 的数组。
大家有没有发现。在解答leetcode题目的时候,大多数标注难度为困难的题目,反而代码量少。 只要找到解题思路和切入点。就可以快速的解出来题目。一定要认真审题。