LeetCode题解 -- 双指针(42)

Trapping Rain Water

Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it is able to trap after raining.

经典的接雨水问题

方法一:
第 i 块区域积水面积 = Min( Max(h[0…i]) , Max(h[i…n]) ) - h[i]

时间复杂度:O(n^2)
空间复杂度:O(n)

class Solution {
    public int trap(int[] height) {
        
        int length = height.length;
        if(length <= 2)
            return 0;
        int[] sum = new int[length];
        int result = 0;
        sum[0] = 0;
        sum[length - 1] = 0;
        for(int i = 1;i < length - 1;i++){
            int leftH = getMax(height,0,i);
            int rightH = getMax(height,i,length - 1);
            sum[i] = Math.min(leftH,rightH) - height[i];
        }

        for(int s : sum){
            result += s;
        }
        return result;
    }
    
    public int getMax(int[] height,int start,int end){
        int max = Integer.MIN_VALUE;
        for(int i = start;i <= end;i++){
            if(height[i] > max){
                max = height[i];
            }
        }
        return max;
    }
}

方法二:
通过dp优化方法一,减少查找左右最高点的次数

时间复杂度:O(n)
空间复杂度:O(n)

class Solution {
    public int trap(int[] height) {
        int length = height.length;
        if(length < 3)
            return 0;
        int[] left = new int[length];
        left[0] = height[0];

        int[] right = new int[length];
        right[length - 1] = height[length - 1];

        int[] sum = new int[length];
        sum[0] = 0;
        sum[length - 1] = 0;

        int result = 0;

        for(int i = 1;i < length;i++){
            left[i] = Math.max(left[i - 1],height[i]);
        }
        for(int j = length - 2;j >= 0;j--){
            right[j] = Math.max(right[j + 1],height[j]);
        }

        for(int k = 1;k < length - 1;k++){
            result += Math.min(left[k],right[k]) - height[k];
        }

        return result;
    }
}

方法三:使用双指针,左右指针分别记录左,右当前的最大值。

因为i 到 j 之间,某一区域k可以接的雨水只与左右板最小值和k区域自身高度有关

时间复杂度:O(n)
空间复杂度:O(1)

class Solution {
    public int trap(int[] height) {
        int length = height.length;
        if(length < 3){
            return 0;
        }
        int start = 0;
        int end = length - 1;
        int result = 0;

        int max_l = height[0];
        int max_r = height[length - 1];
        while(start < end){
            if(max_l < max_r){
                result += max_l - height[start];
                max_l = Math.max(max_l,height[++start]);
            }else{
                result += max_r - height[end];
                max_r = Math.max(max_r,height[--end]);
            }
        }
        return result;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值