Leetcode 42. Trapping Rain Water [hard][java]

本文详细解析了四种解决雨水蓄积问题的算法方案,包括动态规划、双指针优化、简化双指针及栈的应用。每种方法都附带了具体实现代码,深入探讨了时间与空间复杂度。

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.
在这里插入图片描述

Solution 1:dynamic programming

  1. For each h in height, find the largest height to its left and the largest height to its right.
  2. For each h, if h is less than the smaller height of its two sides, add the height difference to the result.

Time Complexity: O(n), space complexity: O(n)

class Solution {
    public int trap(int[] height) {
        if(height == null || height.length == 0)
            return 0;
        
        int[] left = new int[height.length];
        left[0] = height[0];
        for(int i = 1; i < height.length; i++) {
            left[i] = Math.max(left[i-1], height[i]);
        }
        
        int[] right = new int[height.length];
        right[height.length-1] = height[height.length-1];
        for(int i = height.length-2; i >= 0; i--) {
            right[i] = Math.max(right[i+1], height[i]);
        }
        
        int res = 0;
        for(int i = 1; i < height.length-1; i++) {
            int h = Math.min(left[i], right[i]);
            if(h > height[i]) {
                res+=h-height[i];
            }
        }
        return res;
    }
}

Solution 2: Similar to solution 1, but use two pointers so as to reduce the looping times
在这里插入图片描述

Time Complexity: O(n), space Complexity: O(1)

class Solution {
    public int trap(int[] height) {
        if(height == null || height.length == 0)
            return 0;
        
        int left = 0;
        int right = height.length-1;
        int left_max = 0;
        int right_max = 0;
        int res = 0;
        
        while(left < right) {
            if(height[left] < height[right]) {
                if(height[left] >= left_max)
                    left_max = height[left];
                else
                    res += left_max-height[left];
                ++left;
            } else {
                if(height[right] >= right_max)
                    right_max = height[right];
                else
                    res += right_max-height[right];
                --right;
            }
        }
        
        return res;
    }
}

Solution 3: a simpler version of solution 2
Time complexity: O(n), space complexity: O(1)

class Solution {
    public int trap(int[] height) {
        
        int l = 0, r = height.length - 1, level = 0, res = 0;
        while (l < r) {
            int lower = height[(height[l] < height[r]) ? l++ : r--];
            level = Math.max(level, lower);
            res += level - lower;
        }
        return res;
    }
}

Solution 4: use stack (last in first out)

  1. Use stack to store indices
  2. For each iteration,
    (1) If the stack is empty or the current height <= height at the top of the stack, push the current index to stack.
    (2)Otherwise, pop the top index from the stack. If stack is empty, there are no water to be trapped. If stack is not empty, the water is trapped by the height which is min(current height, height of the top index of the stack), and the width is (current index - top index in the stack -1.)
    在这里插入图片描述
class Solution {
    public int trap(int[] height) {
        Stack<Integer> s = new Stack();
        int res = 0;
        for(int i = 0; i < height.length; ) {
            if(s.isEmpty() || height[i] <= height[s.peek()])
                s.push(i++);
            else {
                int t = s.pop();
                if(s.isEmpty())
                    continue;
                
                res += (Math.min(height[s.peek()], height[i])-height[t])*(i-s.peek()-1);
            }
        }

        return res;
    }
}

Reference

  1. https://leetcode.com/problems/trapping-rain-water/solution/
  2. https://www.cnblogs.com/grandyang/p/4402392.html
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值