Trapping Rain Water: Optimal Solution (Data-Backed Guide)

By DSA Prep Team · March 4, 2026 · 10 min read · Algorithms

Trapping Rain Water is the #7 most asked LeetCode problem globally — and the most well-known HARD problem that every serious candidate must own.

Our analysis of 10,385 verified interview questions across 259 companies shows this appeared 100 times across 42 companies — including Google, Amazon, Meta, Microsoft, Goldman Sachs, Citadel, Jane Street, Bloomberg, and Airbnb.

Most candidates know the O(n) DP approach with prefix/suffix arrays. But the optimal solution — O(n) time, O(1) space using two pointers — is what separates good answers from great ones. This guide walks through all three approaches so you can explain the progression clearly in an interview.

Table of Contents

The Data: Why Finance + FAANG Both Ask This

MetricValue
Total Interview Appearances100 verified mentions
Companies That Ask It42 companies
Global Rank#7 out of 10,385 questions
DifficultyHard
Core PatternsTwo Pointers, DP, Stack, Monotonic Stack

📌 Companies That Ask This Problem

Google, Amazon, Meta, Microsoft, Goldman Sachs, Citadel, Jane Street, Bloomberg, Airbnb, Adobe, Atlassian, BitGo, ByteDance, Cisco, DE Shaw, CrowdStrike, Expedia, Flipkart, Grammarly, IBM, Intel, Intuit, MakeMyTrip, Media.net, Myntra, and 17 more.

Problem Statement

LeetCode #42 — Trapping Rain Water

Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it can trap after raining.

Example
Input:  height = [0,1,0,2,1,0,1,3,2,1,2,1]
Output: 6

Input:  height = [4,2,0,3,2,5]
Output: 9

The Key Insight: Water Level Formula

Water trapped at position i = min(max_left[i], max_right[i]) - height[i].

The water level at any position is determined by the shorter of the two surrounding walls. If the left max is 3 and the right max is 5, water fills up to height 3 at that position (limited by the shorter wall). Then subtract the bar's own height.

💡 The Formula in One Line

water[i] = max(0, min(left_max[i], right_max[i]) - height[i])

The max(0, ...) ensures we never count negative water (when the bar is taller than both walls).

Approach 1: DP with Prefix/Suffix Arrays — O(n) time, O(n) space

Precompute left_max[i] (max height from index 0 to i) and right_max[i] (max height from i to end). Then apply the formula.

Python — O(n) space DP
def trap(height):
    n = len(height)
    if n == 0:
        return 0

    left_max = [0] * n
    right_max = [0] * n

    left_max[0] = height[0]
    for i in range(1, n):
        left_max[i] = max(left_max[i-1], height[i])

    right_max[n-1] = height[n-1]
    for i in range(n-2, -1, -1):
        right_max[i] = max(right_max[i+1], height[i])

    water = 0
    for i in range(n):
        water += min(left_max[i], right_max[i]) - height[i]

    return water

Approach 2: Optimal Two Pointers — O(n) time, O(1) space

The DP approach uses O(n) space for the two arrays. Can we do O(1)? Yes — because we only need the minimum of left_max and right_max at each position. Two pointers let us process whichever side has the smaller max first.

Key observation: If left_max < right_max, then the water at the left pointer is determined by left_max (regardless of what's on the right, since right_max ≥ left_max). Move left pointer inward. Otherwise, process right pointer.

Code in Python, Java & JavaScript

Python 3 — Two Pointers O(1) Space
def trap(height: list[int]) -> int:
    left, right = 0, len(height) - 1
    left_max = right_max = 0
    water = 0

    while left < right:
        if height[left] < height[right]:
            if height[left] >= left_max:
                left_max = height[left]
            else:
                water += left_max - height[left]
            left += 1
        else:
            if height[right] >= right_max:
                right_max = height[right]
            else:
                water += right_max - height[right]
            right -= 1

    return water
Java
class Solution {
    public int trap(int[] height) {
        int left = 0, right = height.length - 1;
        int leftMax = 0, rightMax = 0, water = 0;

        while (left < right) {
            if (height[left] < height[right]) {
                if (height[left] >= leftMax) leftMax = height[left];
                else water += leftMax - height[left];
                left++;
            } else {
                if (height[right] >= rightMax) rightMax = height[right];
                else water += rightMax - height[right];
                right--;
            }
        }
        return water;
    }
}
JavaScript
var trap = function(height) {
    let left = 0, right = height.length - 1;
    let leftMax = 0, rightMax = 0, water = 0;

    while (left < right) {
        if (height[left] < height[right]) {
            if (height[left] >= leftMax) leftMax = height[left];
            else water += leftMax - height[left];
            left++;
        } else {
            if (height[right] >= rightMax) rightMax = height[right];
            else water += rightMax - height[right];
            right--;
        }
    }
    return water;
};

Complexity Analysis

📊 Complexity Summary

ApproachTimeSpace
DP (prefix/suffix arrays)O(n)O(n)
Two PointersO(n)O(1)
Monotonic StackO(n)O(n)

How to Actually Remember This

✅ Your Spaced Repetition Schedule

  1. Today: Implement the DP approach first. Draw the left_max and right_max arrays on paper for [0,1,0,2,1,0,1,3,2,1,2,1].
  2. Day 3: Implement two pointer solution from scratch. Trace through the same example.
  3. Day 7: Solve Container With Most Water (LC #11) — same two pointer pattern, simpler variant.
  4. Day 14: Re-implement two pointer without notes in under 10 minutes.

Tag this on DSAPrep.dev under Two Pointers and Dynamic Programming.

Track on DSAPrep.dev →