42. Receiving rainwater (implemented in java) --LeetCode

topic

42. catch rain

Given n non-negative integers representing the height map of each column with a width of 1, calculate how much rain can be received by the columns arranged in this way after rain.

Example 1:

Insert picture description here

输入: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 个单位的雨水(蓝色部分表示雨水)。 

Example 2:

输入:height = [4,2,0,3,2,5]
输出:9

prompt:

  • n == height.length
  • 0 <= n <= 3 * 10^4
  • 0 <= height[i] <= 10^5

Solution 1: Violence (left and right boundary)

/**
 * 思路:
 * 核心思路:
 * 找到每个坑,计算面积和
 * 每个坑都有左右边界,我们要确定好边界
 *
 * 只要右边界没走到数组的末尾就一直循环
 * 找左边界:记录左边界,只要下一个值比左边界小,就确定了左边界。否则,更新左边界为下一个值
 * 之后向后找右边界:
 * 记录最大的棒子
 * 大于等于左边界就是右边界,否则一直向前找
 * 如果找到数组末尾都没找到大于等于左边界的值,就把最大的棒子作为右边界
 * 找到左右边界后计算坑的面积:min(height[l],hei[r])*(r-l-1)-夹在左右边界中的各个柱子的高度
 */
     public int trap(int[] height) {
    
    
        int sum=0,bar_sum=0,l=0,r = 0;
        while (r<height.length-1) {
    
    
            for (int i = l+1; i < height.length; i++) {
    
    
                if (i==0||height[i] >= height[i - 1]) l = i;
                else break;
            }
            int  max_bar=l+1;
            for (int i = l + 1; i < height.length; i++) {
    
    
                //如果当前棒子大于max_bar就记录
                max_bar=height[max_bar]>height[i]?max_bar:i;
                if (height[i] >= height[l]) {
    
    
                    r = i;
                    break;
                }
            }
            if (max_bar>=height.length)break;
            //如果没有找到大于等于左棒子的,就把max_bar作为右棒子
            if (r<=l) {
    
    
                r=max_bar;
            }
            int area = Math.min(height[l], height[r]) * (r - l - 1);
            for (int j = l + 1; j < r; j++) {
    
    
                bar_sum += height[j];
            }
            sum += area - bar_sum;
            l = r;
            bar_sum = 0;
        }
        return sum;
    }

Time complexity: On^2

Space complexity: O1
Insert picture description here

Solution 2: Violence (vertical water injection)

/**
 * 思路:
 * 核心思路:给每一列的柱子注水,每个的柱子的最大注水量
 *
 * 头和尾的柱子无法注水,其他的柱子注水时,当前柱子能注多少水取决于,他左边最大的柱子和右边最大的柱子的高度。
 * 如果当前柱子小于左右最大柱子时才可能注水
 * 最大注水=min(height[l_max],height[r_max])-height[current]
 */
     public int trap(int[] height) {
    
    
        int sum=0;
        for (int current=1;current<height.length-1;current++){
    
    
            int l_max=current-1,r_max=current+1;
            for (int l=current-1;l>=0;l--){
    
    
                if (height[l]>height[l_max])l_max=l;
            }
            for (int r=current+1;r<height.length;r++){
    
    
                if (height[r]>height[r_max])r_max=r;
            }
            int min_bar = Math.min(height[l_max], height[r_max]);
            if (min_bar>height[current]) {
    
    
                sum += min_bar - height[current];
            }
        }
        return sum;
    }

Time complexity: On^2

Space complexity: O1
Insert picture description here

Solution 3: Left and right pinching

/**
 * 思路:
 * 从左到右,把每个柱子最多能注的水累加起来
 *
 * 记录左右柱子中最小的那个lower(地平线)
 * 比较当前地平线lower是否高于level(水库高度)
 * level-lower=当前柱子最大承载的水量
 */
    public int trap(int[] height) {
    
    
        int l=0,r=height.length-1,lower=0,level=0,water=0;
        while (r>l){
    
    
            lower=Math.min(height[l],height[r]);
            level=Math.max(level,lower);
            water+=level-lower;
        }
        return water;
    }

Time complexity: On

Space complexity: O1
Insert picture description here

Solution 4: Stack

/**
 * 思路:
 * 核心思路:
 * 积水的面积 = 当前棒子和最低的那个棒子的高度差 * 他们的距离。
 *
 * 当前值小于栈顶元素就说明可能有积水产生,入栈
 * 如果当前值大于栈顶元素,说明积水产生,出栈当前栈顶元素
 * 比较栈顶和当前值的,找出小的那个min(积水产生的最大高度)。
 * 求出栈顶和当前元素的距离 *(min-出栈的元素值)
 */
     public int trap(int[] height) {
    
    
        ArrayDeque<Integer> stack = new ArrayDeque<>();
        int sum=0;
        for (int current=0;current<height.length;current++){
    
    
            while (!stack.isEmpty()&&height[current]>=height[stack.peek()]){
    
    
                Integer pop = stack.pop();
                if (stack.isEmpty())break;
                int distance=current-stack.peek()-1;
                int min=Math.min(height[stack.peek()],height[current]);
                int area=(min-height[pop])*distance;
                sum+=area;
            }
            stack.push(current);
        }
        return sum;
    }

Time complexity: On^2

Space complexity: On
Insert picture description here

Guess you like

Origin blog.csdn.net/qq_38783664/article/details/110956051