42. 接雨水

36 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第14天,点击查看活动详情

每日刷题 2022.10.12

题目

  • 给定 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
  • 1 <= n <= 2 * 104
  • 0 <= height[i] <= 105

解题思路

  • 思路:首先找到地形的最高处,由最高处的墙体可以将地形分成2部分(也可能是3部分)
  • 设置left=0right=len-1,分别从两端往最高处遍历
  • height[left]>height[left+1]时,说明height[left+1]处需要填补,记录填补的大小,知道最高处停止
  • leftright都到了最高点处时,leftright之间的填补量可直接计算

AC代码

var trap = function(height) {
    let ans = 0;
    const stack = [];//单调递减栈。存放的是下标哦
    const n = height.length;
    for (let i = 0; i < n; ++i) {//循环heights
      	//当前柱子的高度大于栈顶柱子的 不断出栈
        while (stack.length && height[i] > height[stack[stack.length - 1]]) {
            const top = stack.pop();
            if (!stack.length) {//栈为空时 跳出循环
                break;
            }
            const left = stack[stack.length - 1];//拿到当前位置左边比当前柱子矮的位置
            const currWidth = i - left - 1;//计算宽度
            const currHeight = Math.min(height[left], height[i]) - height[top];//计算高度
            ans += currWidth * currHeight;//计算当面积
        }
        stack.push(i);//加入栈
    }
    return ans;
};