一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第 13 天,点击查看活动详情。
接雨水
给定 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
提示:
n == height.length1 <= n <= 2 *0 <= height[i] <=
思路分析
方法一
- 方法一依旧采用暴力解法;
- 两次遍历数组,找到当前元素左、右两侧的最大储水量,然后减去当前元素的值,即为当前元素的最大储水量;
- 将所有元素的最大储水量相加,即为总的最大储水量;
- 但是,采用暴力解法最后总是有可能得到超时的结果,因此还是要使用其他方法来解决。
方法二
- 分析题目,可知对于每个柱子能储多少水,在于它左边的最高柱子和右边的最高柱子,这两个中的最小值即为每个柱子的最大储水能力;
- 如果这个最小值减去柱子本身的值小于0,则证明这根柱子没办法储水,否则它的最大储水值就是最小值减去当前柱子的高度;
- 因此定义两个数组
left和right,分别表示第i个柱子左侧和右侧的最高柱子,循环遍历得出这两个数组的值; - 然后按照步骤二分析,得出最终的最大储水值。
AC 代码
方法一
/**
* @param {number[]} height
* @return {number}
*/
var trap = function(height) {
let res = 0
let len = height.length
for (let i = 1; i < len - 1; i++) {
let left = 0, right = 0
for (let j = i; j >= 0; j--) {
left = Math.max(left, height[j])
}
for (let j = i; j < len; j++) {
right = Math.max(right, height[j])
}
res += Math.min(left, right) - height[i]
}
return res
};
结果:
- 执行结果: 超出时间限制
方法二
/**
* @param {number[]} height
* @return {number}
*/
var trap = function(height) {
const len = height.length
const left = new Array(len).fill(0)
const right = new Array(len).fill(0)
let max = height[0]
for (let i = 1; i < len; i ++) {
left[i] = max
max = Math.max(max, height[i])
}
max = height[len - 1]
for (let i = len - 2; i >= 0; i --) {
right[i] = max
max = Math.max(max, height[i])
}
let res = 0
for (let i = 1; i < len - 1; i ++) {
const cur = height[i]
const min = Math.min(left[i], right[i])
if (min > cur) {
res += (min - cur)
}
}
return res
};
结果:
- 执行结果: 通过
- 执行用时:64 ms, 在所有 JavaScript 提交中击败了84.03%的用户
- 内存消耗:43.6 MB, 在所有 JavaScript 提交中击败了36.58%的用户
- 通过测试用例:321 / 321