LeetCode42. 接雨水 | 刷题打卡

310 阅读1分钟

一、题目描述

难度 困难

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

示例 1:

image.png

输入: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
0 <= n <= 3 * 104
0 <= height[i] <= 105

二、思路分析

可以接雨水的柱子,它左右两边都得有比它高的柱子;

它能存的水,取决于它左右两边的最大值中较小的一个;

这个问题可以用单调递减栈去解决;从左到右,它左边比它高的柱子是可以确定的,然后用单调栈去找右边比它高的柱子

三、AC代码

var trap = function (height) {
  // 没3个柱子都存不住水
  if (height.length <= 2) return 0;
  let water = 0;
  let stack = [];
  // console.log(height);
  for (let i = 0; i < height.length; i++) {
    // 当前元素如果大于栈顶元素,则栈顶元素出栈,判断是否能接雨水
    while (height[i] > height[stack[stack.length - 1]]) {
      let index = stack.pop();
      // 限制条件:栈为空即左边没有柱子了,不能存水;两个柱子高度相同也不能存水
      if (stack.length <= 0 || height[index] === height[stack[stack.length - 1]]) continue;
      // 能存的水,取决于它左右两边的最大值中较小的一个
      let min = Math.min(height[i], height[stack[stack.length - 1]]);
      let temp = (min - height[index]) * (i - stack[stack.length - 1] - 1);
      water += temp;
      // console.log(`第${stack[stack.length - 1] + 1}个柱子到第${i + 1}个柱子之间存储的水:${temp}`);
    }
    stack.push(i);
    // console.log('下标栈:', stack);
  }
  return water;
};

运行过程:

image.png

四、总结

解算法题要找到核心,找到限制条件

接雨水的核心就是找到左右两边比它高的柱子