42. 接雨水 【@我的刷题日记】

难度:困难                日期:2023年5月14

给定 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

方法一:遍历+双指针

思路:从前往后遍历,定义slow fast两个边界量,判断fast>=slow时,fast-slow是否 >1 如果不是则将slow赋值为fast;是 则从slow到fast遍历,用两边哪个高度更低,取更低的那个减去每一个height[i],再相加。

var trap = function(height) {
    let slow = 0;
    let contain = 0;
    for(fast = 1;fast < height.length;fast++){
        if(fast-slow>1 && height[fast]>=height[slow]){
            let temp = height[slow];
            while(slow<fast){
                contain += temp-height[slow++]
            }
        }else if(fast-slow==1 && height[fast]>=height[slow]){
            slow = fast;
        }
    }
    let max = height[--fast];
    while(fast>slow){
        max = Math.max(max,height[fast-1]);
        contain += max - height[fast-1];
        fast--;
    }
    return contain;
};

结果

方法二:动态规划

思路:从左向右遍历,找到每一个height[i] 的 最大高度,存入leftMax数组。同理,从右向左遍历,存入rightMax数组。将每一个i位置的leftMax 和 rightMax进行比较,取较小的那个,与height[i]相减,再将结果相加。

var trap = function(height) {
    let n = height.length;
    if(n==0){
        return 0;
    }

    let arrLeft = new Array(n).fill(0);
    arrLeft[0] = height[0];
    for(let i = 1;i < n;i++){
        arrLeft[i] = Math.max(height[i],arrLeft[i-1]);
    }

    let arrRight = new Array(n).fill(0);
    arrRight[n-1] = height[n-1];
    for(let i = n-2;i >= 0;i--){
        arrRight[i] = Math.max(height[i],arrRight[i+1]);
    }

    let contain = 0;
    for(let i = 0;i < n;i++){
        contain += Math.min(arrLeft[i],arrRight[i])-height[i];
    }
    return contain;
};

结果

方法三:双指针

思路:解决动态规划两个数组储存空间复杂度较大的问题,设置left,right两个变量,记录左右两边的当前位置。判断两边哪个最大高度比较小,取小的那一边的最大高度减去当前高度,然后那一边的left/right前移。

var trap = function(height) {
    let n = height.length;
    let left = 0,right = n-1;
    let leftMax = height[0];
    let rightMax = height[n-1];
    let contain = 0;
    while(left < right){
        leftMax = Math.max(leftMax,height[left]);
        rightMax = Math.max(rightMax,height[right]);
        if(leftMax>rightMax){
            contain += rightMax-height[right--];
        }else{
            contain += leftMax-height[left++];
        }
    }
    return contain;
};

思路 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值