Leetcode(Java)-42. Connected to rainwater

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

Above is the height map represented by array [0,1,0,2,1,0,1,3,2,1,2,1], in this case, it can be connected to 6 units of rainwater (the blue part represents rainwater). Thank you, Marcos, for your contribution.

Example:

Input: [0,1,0,2,1,0,1,3,2,1,2,1]
Output: 6

Idea 1: one layer at a time. For each layer, every 0 between start and end is the rainwater complexity O(n * height)

class Solution {
    public int trap(int[] height) {
        if(height.length==0)
            return 0;
        int weight = 0;
        int start = 0;
        int end = height.length - 1;
        while(start != end)
        {
            start = 0;
            end = height.length - 1;
            while(height[start] == 0)
            {
                start++;
                if(start == height.length-1)
                    return weight;
            }
            while(height[end] == 0)
            {
                end--;
            }
            if(start != end)
            {
                for(int i=start+1;i<=end-1;i++)
                {
                    if(height[i]==0)
                        weight++;
                }
                for(int i=0;i<height.length;i++)
                {
                    if(height[i] > 0)
                        height[i]--;
                }
            }
        }
        return weight;
    }
}

 

Train of thought 2: find the highest wall on the left and right for each column

public int trap(int[] height) {
    int sum = 0;
    //The columns at the ends need not be considered, because there must be no water. So subscripts from 1 to length - 2
    for (int i = 1; i < height.length - 1; i++) {
        int max_left = 0;
        //Find the highest on the left
        for (int j = i - 1; j >= 0; j--) {
            if (height[j] > max_left) {
                max_left = height[j];
            }
        }
        int max_right = 0;
        //Find the highest on the right
        for (int j = i + 1; j < height.length; j++) {
            if (height[j] > max_right) {
                max_right = height[j];
            }
        }
        //Find the smaller one at both ends
        int min = Math.min(max_left, max_right);
        //There will be no water only if the smaller section is higher than the height of the current column. In other cases, there will be no water
        if (min > height[i]) {
            sum = sum + (min - height[i]);
        }
    }
    return sum;
}

Train of thought 3:

We note that solution two is in. For each column, we find that the highest wall on the left and the highest wall on the right are all re traversal of all heights. Here we can optimize it.

First, two arrays are used. max_left [i] represents the height of the highest wall on the left of column I, and max_right[i] represents the height of the highest wall on the right of column I. (be sure to note that the highest wall on the left (right) side of column I does not include itself, which is different from what is mentioned above in leetcode.)

For max'u left, we can actually do this.

max_left [i] = Max(max_left [i-1],height[i-1]). The highest height on the left of the wall in front of it and the height of the wall in front of it are the highest wall on the left of the current column.

We can do this for max'u right.

max_right[i] = Max(max_right[i+1],height[i+1]) . The highest height on the right side of the wall behind it and the height of the wall behind it are the highest walls on the right side of the current column.

In this way, we can use the algorithm of solution two again, so that we don't need to go through the for loop once again to find Max left and Max right.

public int trap(int[] height) {
    int sum = 0;
    int[] max_left = new int[height.length];
    int[] max_right = new int[height.length];
    
    for (int i = 1; i < height.length - 1; i++) {
        max_left[i] = Math.max(max_left[i - 1], height[i - 1]);
    }
    for (int i = height.length - 2; i >= 0; i--) {
        max_right[i] = Math.max(max_right[i + 1], height[i + 1]);
    }
    for (int i = 1; i < height.length - 1; i++) {
        int min = Math.min(max_left[i], max_right[i]);
        if (min > height[i]) {
            sum = sum + (min - height[i]);
        }
    }
    return sum;
}

 

240 original articles published, 34 praised, 20000 visitors+
Private letter follow

Posted by glory452 on Sun, 16 Feb 2020 22:40:18 -0800