Trapping Rain Water

Question (LC.42)

Given an integer array representing the height of n unit width bars, find volume of rain water it can trap.

Example

I: [0,1,2]
O: 0
I: [3,1,2]
O: 1
I: [0,1,0,2,1,0,1,3,2,1,2,1]
O: 6

Analysis

The water being trapped inside any bar is determined by the highest left and right bar. The volume of water trapped = min(left, right) - height

Brute Force Three Pass

We can assign the highest left bars, assign the highest right bars, then compute the rain water.

public int trap(int[] height) {
    if (height == null || height.length == 0) {
        return 0;
    }
    int n = height.length;
    int[] leftBars = new int[n];
    int[] rightBars = new int[n];
    // assign left bars
    int left = 0;
    for (int i = 0; i < n; i++) {
        left = Math.max(left, height[i]);
        leftBars[i] = left;
    }
    // assign right bars
    int right = 0;
    for (int i = n - 1; i >= 0; i--) {
        right = Math.max(right, height[i]);
        rightBars[i] = right;
    }
    // compute the rain volume
    int rain = 0;
    for (int i = 1; i < n - 1; i++) {
        int current = Math.min(leftBars[i], rightBars[i]) - height[i];
        rain += current > 0 ? current : 0;
    }
    return rain;
}

Time O(3n) = O(n) Space O(2n) = O(n)

L/R Pointers

Linear time is probably as good as we can get. Unless we can do a binary search on the array. But the space can be further optimized.

We maintain two values leftBar and rightBar. Then use left/right pointers to update on the way.

Time O(n) Space O(1)

Follow Up (LC.407)

Trap rain water 3D version

Last updated