Problem Statement
Trapping Rain Water
Picture a row of walls of different heights standing side by side, each one bar wide. After it rains, water settles in the dips between taller walls. The numbers in the list tell you how tall each wall is. Your job is to figure out how many squares of water get trapped in all the dips put together.
Signals to notice
Brute force first
For each position, find the max height to its left and right. Re-scans the array for every position. It is a fair place to begin because it matches the surface of the question, yet it does not capture the deeper structure that makes the problem simpler.
The key insight
Two pointers from both ends converging inward. Water at any position = min(maxLeft, maxRight) - height. Move the pointer with the smaller max — you know the water level is bounded by the smaller side. The goal is not to be clever for its own sake, but to remember the one relationship that keeps the solution grounded as you move forward.
Trace it on height=[0,1,0,2,1,0,1,3,2,1,2,1]
init: left=0,right=11,lMax=0,rMax=0,water=0 l=0: h=0<=h[11]=1, 0>=lMax -> lMax=0, left->1; l=1: h=1<=h[11], 1>=lMax -> lMax=1, left->2 l=2: h=0<=h[11]=1, 0<lMax(1) -> water+=1=1, left->3 l=3: h=2>h[11]=1 -> rMax=1, right->10; then h[3]=2>=lMax(1) -> lMax=2, left->4 l=4..6: h=1,0,1 all <lMax(2) -> water+=1+2+1, water=5, left->7 l=7: h=3>h[10]=2 -> rMax=2, right->9 r=9: h=1<rMax(2) -> water+=1=6, right->8; r=8: h=2>=rMax(2) -> rMax=2, right->7 left=7,right=7: left<right false, return water=6
What must stay true
Water at position i = min(maxLeft, maxRight) - height[i]. If maxLeft < maxRight, the water level at the left pointer is determined by maxLeft regardless of what's further right — so you can safely compute it and move inward. If that remains true after every update, the rest of the reasoning has a stable place to stand.
Shape of the loop
left, right = 0, n-1; leftMax = rightMax = 0; water = 0
while left < right:
if height[left] <= height[right]:
leftMax = max(leftMax, height[left]); water += leftMax - height[left]; left++
else:
rightMax = max(rightMax, height[right]); water += rightMax - height[right]; right--
return waterPseudocode only — the full worked solution lives in the Solution tab.
Easy way to go wrong
Not understanding WHY you move the smaller side — if maxLeft < maxRight, no bar to the right can make the left pointer's water level higher. It's bounded by maxLeft, period. When the code becomes mechanical before the idea is clear, small edge cases start breaking the whole story.