算法刷题 -- 42. 接雨水 <难度 ★★★>

1、力扣原题

https://leetcode-cn.com/problems/trapping-rain-water/
在这里插入图片描述

  • 解题思路一: 动态规划
    1.按列求,每一列能接多少雨水,取决于左右两边的大小
    2.根据木桶效应,应该由左右两边最短的那个“墙”高度决定
class Solution {
    public int trap(int[] height) {
        int count = height.length;
        int[] max_left = new int[count]; // 每个数组元素的值默认为0
        int[] max_right = new int[count];
        int result = 0;

        for (int i = 1; i < count - 1; i++) { // 第i列,左边的一个高度 & 左边的一个的左边最高的,取最大值
            max_left[i] = Math.max(max_left[i - 1], height[i - 1]);
        }

        for (int i = count - 2; i > 0; i--) { // 第i列,右边的一个高度 & 右边的一个的右边最高的,取最大值
            max_right[i] = Math.max(max_right[i + 1], height[i + 1]);
        }

        for (int i = 0; i < count; i++) {
            int min = Math.min(max_left[i],max_right[i]);
            if (min > height[i]) {
                result += min - height[i];
            }
        }

        return result;
    }
}

在这里插入图片描述

  • 思路二:单调递减栈
    1.墙的高度小于或等于前面的高度,说明当前不能接住雨水
    2.墙的高度大于前面的高度,并且间距大于1,才能接住雨水
    3.每次雨水的计算方法:墙的间距乘以高度(这个高度是左右两边最小值减去当前值)
class Solution {
   public int trap(int[] height) {
       int sum = 0;
       Stack<Integer> mStack = new Stack<>();

       for (int i = 0; i < height.length - 1; i++) {
           mStack.push(i);
           int rightVal = height[i+1];  // 右边的高度
           while (!mStack.isEmpty() && height[mStack.peek()] < rightVal) {
               int curVal = height[mStack.peek()]; // 当前的高度
               mStack.pop();
               if (mStack.isEmpty()) {
                   break; // 栈为空,停止本次计算
               }
               int distance = i - mStack.peek(); // 横轴之间的距离,即当前雨水的宽度
               int leftVal = height[mStack.peek()]; // 左边的高度
               int minVal = Math.min(leftVal,rightVal); // 取最小值
               int h = minVal - curVal; // 雨水的高度
               sum += h * distance; // 计算雨水数量
           }
       }
       return sum;
   }
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值