Trapping Rain Water
Given an elevation map where width of each bar is 1, compute how much water it can trap after raining. The classic masterclass in two-pointer bottleneck derivation.
Problem Statement
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.
Examples & Constraints
- n == height.length
- 1 <= n <= 2 * 10^4
- 0 <= height[i] <= 10^5
Two Pointers with Running Max Boundaries (O(1) Space)
Optimal ApproachConverge left and right pointers while tracking maxLeft and maxRight. The trapped water at the lower boundary is min(maxLeft, maxRight) - height[i], computed in O(1) auxiliary space.
Each step moves either the left or right pointer by one bar. The two pointers traverse the array of length N in a single pass.
Operates strictly in-place with four primitive scalar variables (left, right, maxLeft, maxRight). Zero auxiliary arrays allocated.
Underlying algorithmic logic
The Water Level Formula
At any index i, the water held directly above the bar is:water[i] = max(0, min(max_left, max_right) - height[i])
Where max_left is the tallest bar to the left of i, and max_right is the tallest bar to the right of i.
The Two-Pointer Optimization: Eliminating Arrays
A standard dynamic programming solution computes two auxiliary arrays (leftMax and rightMax) in O(n) space.
However, notice:
- If
maxLeft < maxRight, the water trapped aboveleftis strictly bounded by `maxLeft`! It does not matter how much tallermaxRightgets in the future; the bottleneck is already determined bymaxLeft. - Conversely, if
maxRight <= maxLeft, the water trapped aboverightis strictly bounded by `maxRight`.
Algorithm:
- Initialize
left = 0,right = n - 1. - Initialize
maxLeft = 0,maxRight = 0, andtotalWater = 0. - While
left < right:
- If
height[left] < height[right]: - If
height[left] >= maxLeft, updatemaxLeft = height[left]. - Else, add
maxLeft - height[left]tototalWater. - Advance
left++. - Else:
- If
height[right] >= maxRight, updatemaxRight = height[right]. - Else, add
maxRight - height[right]tototalWater. - Decrement
right--.
- Return
totalWater.
Step-by-step execution walkthrough
height = [0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1]. left = 0 (val 0), right = 11 (val 1). maxLeft = 0, maxRight = 0.
i=0: maxLeft=0. i=1: maxLeft=1. i=2 (height 0): height[2] < maxLeft (1) -> trapped = 1 - 0 = 1.
Water accumulates over indices 4, 5, 6 as left advances towards the peak at index 7 (height 3).
Pointers meet at index 7 (highest bar). Total accumulated water is exactly 6 units.
- •Optimal O(n) single pass runtime
- •O(1) auxiliary space without requiring extra prefix/suffix arrays
- •The logic condition (advancing based on height[left] < height[right]) requires careful proof
Code Implementations
Ready-to-useCopy & paste production-ready solutions for Two Pointers with Running Max Boundaries (O(1) Space) in your language of choice
def trap(height: list[int]) -> int:if not height:return 0left, right = 0, len(height) - 1max_left, max_right = 0, 0total_water = 0while left < right:if height[left] < height[right]:if height[left] >= max_left:max_left = height[left]else:total_water += max_left - height[left]left += 1else:if height[right] >= max_right:max_right = height[right]else:total_water += max_right - height[right]right -= 1return total_waterif __name__ == "__main__":test1 = [0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1]test2 = [4, 2, 0, 3, 2, 5]print("test1 trapped water:", trap(test1))print("test2 trapped water:", trap(test2))
Understand Array & Matrix Visually
Explore sequential element access, subsegment manipulations, insertion, deletion, and 2D grid matrix walks. Test live edge cases and watch memory state transitions step-by-step.
Frequently Asked Questions
Related Logic & Algorithm Problems
Container With Most Water
Find two vertical lines that together with the x-axis form a container holding the maximum amount of water. The premier problem for learning two-pointer greedy bottleneck elimination.
Two Sum
Find the two numbers in an array that sum up to a target value. The quintessential problem for learning how to trade memory for speed using a Hash Map.
Valid Palindrome
Determine if a string is a palindrome considering only alphanumeric characters and ignoring case. The canonical problem for learning the two-pointer inward convergence technique.