【刷题】接雨水

131 阅读1分钟

题目链接;

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

示例 1:

image

输入: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 个单位的雨水(蓝色部分表示雨水)。

题解:

先尝试用的方式解决,维护一个单调递减的序列。这样做的目的是,当发现有一个高度,比栈顶大,那么就可以从栈内取出两个元素,组成一个低洼地区,将所有低洼地区加起来,就是可以接雨水的量,下面边解题边注释。


function trap(height) {
    /*
    * 虽然这个栈保存的是索引,
    * 但内容一定是单调递减的
    * 因为一旦有发现比现在值更低的,就会不断的组成低洼,并pop掉
    */
    const stack = [];
    
    const len = height.length;
    
    let i = 0, ans = 0;
    
    while(i < len) {
        const curr = height[i];
        
        // 当遇到更高的高度,说明可以组成一个低洼地区
        while(stack.length && curr > height[stack[stack.length - 1]]) {
            const mid = stack.pop();
            if (!stack.length) {
                // 左边无法围住的话,无法形成低洼,直接break即可
                break;
            }
            // 这里不直接pop掉的原因是:
            // 因为这个left是一个比mid更高的高度
            // 说不定之后也会有一个相同高度,或者更高的,与left组成一个低洼地区
            // 所以不能直接pop掉
            const left = stack[stack.length -1];
            
            // 当前低洼地区的高度,取决于左右两遍更低的那个高度
            const h = Math.min(curr , height[left]) - height[mid];
            
            const w = i - left - 1;
            
            ans += w * h;
        }
        
        stack.push(i++);   
    }
    
    return ans;
}