LeetCode探索(62):42-接雨水

155 阅读1分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第19天,点击查看活动详情

题目

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。

示例 1:

img

输入: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.length
  • 1 <= n <= 2 * 10^4
  • 0 <= 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

参考