↓Skip to main content
  1. LeetCode/

LeetCode 42: Trapping Rain Water

·2 mins· ·
LeetCode Hard Array Two-Pointers Dynamic-Programming Stack
Wei Yi Chung
Author
Wei Yi Chung
Working at the contributing of open source, distributed systems, and data engineering.
Table of Contents

Meta Data
#

Difficulty: hard First Attempt: 2022-10-27

  • Submissions: Wrong Answer ×6 → Runtime Error ×2 → Time Limit Exceeded → Wrong Answer → Accepted ×5

Approach
#

The water above cell i is set by the shorter of the tallest walls on each side: water[i] = min(leftMax[i], rightMax[i]) - height[i], where both maxima include the cell itself, so the value is never negative.

  • Prefix and suffix maxima (Linear DP Template 6): build both arrays, O(n) space.
  • Two pointers (Two Pointers Template 1): keep lmax and rmax; whichever side has the smaller maximum already knows its water level (the other side has a taller wall), so add it and move inward, O(1) space.

My Attempts
#

This took 15 submissions in one evening:

  • The first six scanned for a “left wall, right wall” basin and computed areas on a fall followed by a rise; they mishandled many shapes, returning 0 even for [4, 3, 4], whose answer is 1.
  • Next, computing max(height[:i]) and max(height[i + 1:]) per cell gave correct answers in O(n²) and timed out.
  • With prefix and suffix maxima, the first version started the prefix loop at 1, leaving cell 0 out of the maximum: [4, 3, 4] still returned 0. Starting at 0 passed, and I finally switched to the two-pointer version.

Solution
#

class Solution:
    def trap(self, height: List[int]) -> int:
        l, r = 0, len(height) - 1
        lmax = rmax = water = 0
        while l < r:
            lmax = max(lmax, height[l])
            rmax = max(rmax, height[r])
            if lmax <= rmax:
                water += lmax - height[l]
                l += 1
            else:
                water += rmax - height[r]
                r -= 1
        return water

Complexity
#

Time O(n), space O(1).

Mistakes to Avoid
#

  • Case analysis on “find a basin and compute its area” rarely covers every shape; compute the level per cell instead.
  • Rescanning both sides for every cell is O(n²) and times out.
  • The prefix maximum must start from cell 0.

Interview Explanation
#

Each cell holds the shorter of the tallest walls on its two sides minus its height. With two pointers I track both maxima; the side with the smaller one has a settled level, so I add it and move inward. Time O(n), space O(1).

Related

LeetCode 167: Two Sum II - Input Array Is Sorted
·2 mins
LeetCode Medium Array Two-Pointers Binary-Search
LeetCode 167 note: sorted, so move two pointers inward, shifting right when the sum is too large and left when too small; indices are 1-based
LeetCode 75: Sort Colors
·2 mins
LeetCode Medium Array Two-Pointers Sorting Quicksort
LeetCode 75 note: the Dutch flag, with 0s left of low and 2s right of high; after swapping a 2 to high, do not advance, since the swapped-in value is unchecked
LeetCode 80: Remove Duplicates from Sorted Array II
·1 min
LeetCode Medium Array Two-Pointers
LeetCode 80 note: keep each value at most twice by comparing with nums[k - 2], two slots back from the write position
LeetCode 31: Next Permutation
·2 mins
LeetCode Medium Array Two-Pointers
LeetCode 31 note: from the right find the first dip i, swap it with the smallest larger value to its right, then reverse everything after i, with comparisons that include equality
LeetCode 11: Container With Most Water
·2 mins
LeetCode Medium Array Two-Pointers Greedy
LeetCode 11 note: start pointers at both ends and always move the shorter side; moving the taller side only narrows the width without raising the height
LeetCode 15: 3Sum
·2 mins
LeetCode Medium Array Two-Pointers Sorting
LeetCode 15 note: sort, fix the first number, and find the other two with converging pointers, skipping equal values at all three positions to avoid duplicate triplets