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.

hardStackTwo PointersTwo PointersTime: O(n) · Space: O(1)

Signals to notice

trapped water between barswater level at each positionbounded by shorter side

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 water

Pseudocode 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.

Two Pointers Pattern