一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第19天,点击查看活动详情。
题目
给定 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 * 10^40 <= height[i] <= 10^5
思考
本题难度是Hard。
首先是理解题意,我们要接到雨水,柱子的高度要有一定的规律。比如有3根柱子,高度分别为[2, 0, 2],也就是中间低两边高,这样就能接到雨水。如果高度递增或者递减,这样是无法接到雨水的。
对于柱子 i,接到雨水的高度等于该柱子两边的最小高度减去当前柱子的高度。那么,我们可以遍历所有柱子,依次求出左边和右边的最大高度,然后计算出每个柱子能接到的雨水量即可。那么,题目要求计数接到的雨水总量,就等于每个柱子接到的雨水量之和。
代码如下所示。
解答
方法一:动态规划
/**
* @param {number[]} height
* @return {number}
*/
var trap = function (height) {
const len = height.length
if (len === 0) {
return 0
}
const leftMax = new Array(len).fill(0)
leftMax[0] = height[0]
const rightMax = new Array(len).fill(0)
rightMax[len - 1] = height[len - 1]
for (let i = 1, j = len - 2; i < len, j >= 0; ++i, j--) {
leftMax[i] = Math.max(leftMax[i - 1], height[i])
rightMax[j] = Math.max(rightMax[j + 1], height[j])
}
let ans = 0
for (let i = 0; i < len; ++i) {
ans += Math.min(leftMax[i], rightMax[i]) - height[i]
}
return ans
}
// 执行用时:72 ms, 在所有 JavaScript 提交中击败了54.14%的用户
// 内存消耗:43.3 MB, 在所有 JavaScript 提交中击败了49.56%的用户
// 通过测试用例:321 / 321