Trapping Rain Water — A Clean and Simple Solution


The Trapping Rain Water problem is a popular coding challenge that’s common in interviews and competitive programming. It’s simple to describe but requires some careful thought to solve efficiently.


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 1

Input: height = [0,1,0,2,1,0,1,3,2,1,2,1]
Output: 6
Explanation: The above elevation map (black section) is represented by the array.
In this case, 6 units of rain water (blue section) are being trapped.

Example 2

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

Constraints

  • 1 <= n <= 2 * 10⁴

  • 0 <= height[i] <= 10⁵


Understanding the Problem

Imagine each bar is a block in a histogram, and rain falls over it. Water can be trapped between the taller bars if there are lower bars in between.

At any position i:

  • The maximum height to the left is left_max

  • The maximum height to the right is right_max

  • Water trapped at i is:

min(left_max, right_max) - height[i]

(If this value is negative, it’s just 0 — meaning no water trapped.)


My Approach

Instead of maintaining two arrays for left and right maxima or juggling two pointers, I took this approach:

  1. Precompute the right maxima for every index in one backward pass (next_max array).

  2. Track the left maximum while traversing forward.

  3. For each block, the trapped water is:

min(left_max, next_max[i]) - height[i]
  1. Accumulate this into the result.

The Code

from typing import List

class Solution:
    def trap(self, height: List[int]) -> int:
        n = len(height)
        if n < 3:
            return 0

        # Step 1: Build next_max array (right maxima)
        next_max = height[:]
        for i in range(n - 2, -1, -1):
            next_max[i] = max(next_max[i], next_max[i + 1])

        # Step 2: Traverse left to right
        res = 0
        left_max = 0
        for h_right, h in zip(next_max, height):
            left_max = max(left_max, h)
            res += min(left_max, h_right) - h

        return res

Walkthrough Example

Take height = [0,1,0,2,1,0,1,3,2,1,2,1]:

  • Right maxima (next_max) after pass 1:
[3,3,3,3,3,3,3,3,2,2,2,1]
  • Forward pass:

    • Update left_max as we go.

    • Add min(left_max, next_max[i]) - height[i] to total.

  • Total water trapped: 6


Complexity

  • Time: O(n) — one backward pass, one forward pass.

  • Space: O(n) — for the next_max array.


Why This Works Well

  • Readable: Matches the problem definition directly.

  • Efficient: Runs in optimal time.

  • Beginner-friendly: No tricky pointer movements.



0
Subscribe to my newsletter

Read articles from NIKHIL KUMAR REDDY directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

NIKHIL KUMAR REDDY
NIKHIL KUMAR REDDY