Skip to main content

Trapping Rain Water

How to notice that water at each position depends on both side maximums and compress that into two pointers.

Given an array height, where each value represents the height of a bar, return how much water is trapped after raining.

Example:

Input:  height = [0,1,0,2,1,0,1,3,2,1,2,1]
Output: 6

What to notice before coding

Common mistakes

Step 1 - Understand the local formula

At position i, the trapped water is:

min(maxLeft, maxRight) - height[i]

Because the water level can only rise up to the smaller of the two walls that contain it.

Step 2 - Write the most direct baseline

The natural baseline is:

  • for each index
  • find the highest value to the left
  • find the highest value to the right
  • calculate that position's contribution

It works.

But it repeats too much searching.

Step 3 - Ask what really decides one side

If you keep:

  • leftMax as the highest wall seen from the left
  • rightMax as the highest wall seen from the right

then when leftMax <= rightMax, the left side is already decided.

The reason is that, for the current left position, there will always be some wall on the right at least as high as leftMax.

Step 4 - Turn that into two pointers

With two pointers:

  • if leftMax <= rightMax, resolve the left side and advance left
  • otherwise, resolve the right side and move right back

That way, each index is processed once.

The interactive editor needs JavaScript. You can still read the prompt and copy the starter code below.

Starter code

export function trap(height: number[]): number {
  // your solution here
  return 0
}
solution.ts
Stuck? Hints available.

Haven't solved it yet?

Viewing the solution now may reduce learning. It's worth trying a bit more.

Open the reference solution

Without JavaScript, the reference solution is shown inline instead of in a dialog.

Solution

Final complexity

Time: O(n)

Space: O(1)

Solution 1 - Scan left and right for every index O(n²)

Good baseline because it makes the local formula concrete.

export function trap(height: number[]): number {
  let water = 0

  for (let index = 0; index < height.length; index += 1) {
    let leftMax = 0
    let rightMax = 0

    for (let left = 0; left <= index; left += 1) {
      leftMax = Math.max(leftMax, height[left])
    }

    for (let right = index; right < height.length; right += 1) {
      rightMax = Math.max(rightMax, height[right])
    }

    water += Math.max(0, Math.min(leftMax, rightMax) - height[index])
  }

  return water
}

It works, but it recalculates the same maximums many times.

Solution 2 - Two pointers with accumulated maximums in O(n)

Now you resolve each side when it is already decided.

export function trap(height: number[]): number {
  let left = 0
  let right = height.length - 1
  let leftMax = 0
  let rightMax = 0
  let water = 0

  while (left < right) {
    leftMax = Math.max(leftMax, height[left])
    rightMax = Math.max(rightMax, height[right])

    if (leftMax <= rightMax) {
      water += leftMax - height[left]
      left += 1
    } else {
      water += rightMax - height[right]
      right -= 1
    }
  }

  return water
}

The strong insight is knowing when one position can be finalized without knowing the rest in more detail.

What to say in the interview

A strong short explanation would be:

The local formula is min(leftMax, rightMax) - height[i]. The baseline recalculates those maximums for every index. In the stronger version I maintain leftMax and rightMax with two pointers. When leftMax <= rightMax, the left side is already limited and can be resolved immediately. The same logic works symmetrically on the right.

That shows that you:

  • understand the local water formula
  • can justify pointer movement
  • explain why one side’s answer is already decided

When this pattern shows up again

This pattern comes back when you need to:

  • maintain accumulated maximums from both sides
  • decide locally when one side is already resolved
  • use two pointers with stronger invariants
  • compare alternatives like prefix arrays, stack, and two pointers

The point is not memorizing Trapping Rain Water.

The point is learning when partial information is already enough to close one side.

Next challenge Minimum Window Substring Previous challenge Word Break

Related challenges

Related articles