150NeetCode 150

14.Trapping Rain Water

HardTwo Pointers ยท 5/5

Problem

Given n non-negative integers representing an elevation map where every bar has width 1, compute how many units of rain water are trapped between the bars after it rains.

Water sitting above bar i is held in place only if there is a taller-or-equal wall somewhere to its left and somewhere to its right.

Examples

Input:  height = [0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1]
Output: 6
Explanation: Water per index: [0,0,1,0,1,2,1,0,0,1,0,0] โ†’ total 6.
Input:  height = [4, 2, 0, 3, 2, 5]
Output: 9
Explanation: Water per index: [0,2,4,1,2,0] โ†’ total 9.

Constraints

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

๐Ÿ’ก Key Insight

The water above index i is min(maxLeft[i], maxRight[i]) - height[i], where maxLeft[i] is the tallest bar at or left of i and maxRight[i] the tallest at or right of i. The water level is set by the lower of the two walls. Computing those maxima naively is O(nยฒ); precomputing them is O(n) time and space; and two pointers get O(1) space by always processing the side whose wall is lower โ€” because that side's limit is already known for sure.

Brute Force

TimeO(nยฒ)SpaceO(1).

Intuition

Apply the formula directly: for every index, scan left for the tallest bar and scan right for the tallest bar, then add min(leftMax, rightMax) - height[i].

Algorithm

  1. total = 0.
  2. For each i:
    • leftMax = max(height[0..i]), rightMax = max(height[i..n-1]).
    • total += min(leftMax, rightMax) - height[i].
  3. Return total.

Visualization

height = [4, 2, 0, 3, 2, 5]

i=2 (0): leftMax 4, rightMax 5 โ†’ min 4 โˆ’ 0 = 4
i=3 (3): leftMax 4, rightMax 5 โ†’ min 4 โˆ’ 3 = 1

Code

java
class Solution {
    public int trap(int[] height) {
        int n = height.length;
        int total = 0;
        for (int i = 0; i < n; i++) {
            int leftMax = 0, rightMax = 0;
            for (int j = 0; j <= i; j++) {
                leftMax = Math.max(leftMax, height[j]);
            }
            for (int j = i; j < n; j++) {
                rightMax = Math.max(rightMax, height[j]);
            }
            // Including height[i] in both maxima guarantees a non-negative result
            total += Math.min(leftMax, rightMax) - height[i];
        }
        return total;
    }
}

Complexity

  • Time: O(nยฒ) โ€” two linear scans per index.
  • Space: O(1).

Complexity Comparison

Approach Time Space
Brute Force O(nยฒ) O(1)
Prefix and Suffix Max Arrays O(n) O(n)
Monotonic Stack O(n) O(n)
Two Pointers O(n) O(1)

Common Pitfalls

  • Using max(leftMax, rightMax) as the water level โ€” water spills over the lower wall.
  • Excluding height[i] from its own leftMax/rightMax without guarding against negatives โ€” a bar taller than both neighbours would add negative water.
  • In the stack approach, forgetting the stack.isEmpty() check after popping โ€” the leftmost floor has no left wall and holds no water.
  • In the two-pointer approach, moving the pointer on the higher side โ€” its level is not yet determined.