Leetcode42题(Trapping Rain Water) 接雨水 解答记录 JAVA版

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
在这里插入图片描述
上面是由数组 [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

想要接住雨水 数组要大于3 如果只有两个数组无法接住雨水
接住雨水的前提是左右两边的数组高度要大于中间数组形成凹槽 并且雨水的接住量是矮的数组来决定
解法1
新建两个数组 a一个存放左边最大值 b一个存放右边最大值
然后遍历原始数组h,由于木桶效应 承载水的量由短的一边决定 min = min(a[i],b[i])然后比较min和h[i]的大小如果min>h[i] 就累加min-h[i]的值
以上的做法 需要三次遍历
可以把第二次遍历寻找右边最大值和判断min的大小的第三次遍历合成一次遍历
代码如下

public static int getS (int [] height){
        int sum =0;
        int[] a = new int [height.length];
        int[] b = new int [height.length];
        int leftmax=0;
        int rightmax = 0;
        for (int i = 0; i < height.length; i++) {
            a[i] = leftmax;
            leftmax = Math.max(leftmax,height [i]);
        }
        for (int i = height.length - 1; i >=0; i--) {
            a [i]=Math.min(rightmax,a [i]);
            rightmax = Math.max(rightmax,height [i]);
            if(a[i]>height [i]){
                sum += a[i]-height [i];
            }
        }
        return sum;
    }

解法2
使用两个指针,一个在数组的最左边,另一个在数组的最右边 记录指针所在位置的左边最大值和右边最大值 如果左边最大值小于右边最大值就移动左边指针,并且使用左边最大值减去指针位置数组值做累加,反之移动右边指针,直到两个指针相遇
代码如下:

if(height == null || height.length <3){
           return 0;
        }
        int sum = 0;
        int leftmax =0;
        int rightmax =0;
        int i =0;
        int j = height.length -1;
        while (i < j){
            leftmax = Math.max(leftmax,height [i]);
            rightmax = Math.max(rightmax,height [j]);
            if(leftmax<rightmax){
                sum += leftmax - height [i];
                i++;
            }else {
                sum += rightmax - height [j];
                j--;
            }
        }
        return sum;

解法3
使用单调栈来解决接雨水问题
使用一个单调递减栈, 正好可以使用单调递减的性质,当数组中的数据出现比栈顶的数大的时候,来判断是不是可以接住雨水
以[0,1,0,2,1,0,1,3,2,1,2,1]数组为例 下图记录了 单调栈的操作流程
在这里插入图片描述
代码如下:

public static int trap2(int[] height){
        int res = 0;
        int n = height.length;
        Deque<Integer> stack = new ArrayDeque<> ();
        int curIndex = 0;
        while (curIndex < n){
            //peek()查看堆栈顶部的对象,但不从堆栈中移除它
            while (!stack.isEmpty() && height [curIndex]>height [stack.peek()]){
                int top = stack.pop();
                if(stack.isEmpty()){
                   break;
                }
                int h = Math.min(height[stack.peek()],height [curIndex])-height [top];
                int dist = curIndex - stack.peek() - 1;
                res += h*dist;
            }
            stack.push(curIndex++);
        }
        return res;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值