42. Trapping Rain Water
hardAsked at RobinhoodGiven heights representing an elevation map, compute how much water it can trap after raining. Robinhood asks this as a hard-tier classical problem to see whether you reach for two-pointer over DP-of-max-arrays, and whether you can articulate the invariant cleanly.
By Alex Chen, Founder, InterviewChamp.AI · Last verified
Source citations
Public interview reports confirming this problem appears in Robinhood loops.
- Glassdoor (2026-Q1)— Robinhood SWE-II onsite reports include Trapping Rain Water as a recurring hard round.
- Blind (2025-11)— Robinhood backend trip reports cite this and Largest Rectangle in Histogram as the two-pointer / stack hard pair.
Problem
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.
Constraints
n == height.length1 <= n <= 2 * 10^40 <= height[i] <= 10^5
Examples
Example 1
height = [0,1,0,2,1,0,1,3,2,1,2,1]6Example 2
height = [4,2,0,3,2,5]9Approaches
1. Brute-force per index
For each index i, scan left and right for the max heights. Water at i is min(leftMax, rightMax) - height[i].
- Time
- O(n^2)
- Space
- O(1)
function trapBrute(height) {
let total = 0;
for (let i = 0; i < height.length; i++) {
let leftMax = 0, rightMax = 0;
for (let l = 0; l <= i; l++) leftMax = Math.max(leftMax, height[l]);
for (let r = i; r < height.length; r++) rightMax = Math.max(rightMax, height[r]);
total += Math.min(leftMax, rightMax) - height[i];
}
return total;
}Tradeoff: Quadratic. The natural starting point — name it, then move to precomputed-max arrays.
2. DP — prefix/suffix max arrays
Precompute leftMax[i] and rightMax[i]. Then sum min(leftMax[i], rightMax[i]) - height[i].
- Time
- O(n)
- Space
- O(n)
function trapDP(height) {
const n = height.length;
if (!n) return 0;
const leftMax = new Array(n);
const rightMax = new Array(n);
leftMax[0] = height[0];
for (let i = 1; i < n; i++) leftMax[i] = Math.max(leftMax[i - 1], height[i]);
rightMax[n - 1] = height[n - 1];
for (let i = n - 2; i >= 0; i--) rightMax[i] = Math.max(rightMax[i + 1], height[i]);
let total = 0;
for (let i = 0; i < n; i++) total += Math.min(leftMax[i], rightMax[i]) - height[i];
return total;
}Tradeoff: O(n) time and space. Easy to argue correctness. Strong intermediate answer before two-pointer.
3. Two-pointer (optimal)
Walk left and right pointers inward. Track leftMax and rightMax. The lower side determines the water level at that pointer.
- Time
- O(n)
- Space
- O(1)
function trap(height) {
let left = 0, right = height.length - 1;
let leftMax = 0, rightMax = 0;
let total = 0;
while (left < right) {
if (height[left] < height[right]) {
if (height[left] >= leftMax) leftMax = height[left];
else total += leftMax - height[left];
left++;
} else {
if (height[right] >= rightMax) rightMax = height[right];
else total += rightMax - height[right];
right--;
}
}
return total;
}Tradeoff: O(n) time, O(1) space. The optimal. Invariant: 'the lower side's max is bounded by the higher side, so we can safely compute its water without knowing the other side's exact future max.'
Robinhood-specific tips
Robinhood interviewers want all three approaches walked through verbally. Lead with brute-force, name 'this recomputes max scans — I'll memoize into prefix/suffix arrays.' Then say 'I can collapse the two arrays into two pointers because the lower side determines the water at that index, regardless of the higher side's exact future.' Be ready for the 2D variant follow-up (LC 407).
Common mistakes
- Computing height[i] - min(leftMax, rightMax) — wrong direction; should be min(maxes) - height[i].
- In two-pointer, comparing leftMax and rightMax instead of height[left] and height[right] — wrong invariant.
- Off-by-one on the boundary — water above bar 0 or bar n-1 is always 0 because there's no wall on the outside.
Follow-up questions
An interviewer at Robinhood may pivot to one of these next:
- Trapping Rain Water II (LC 407) — 2D grid; BFS from boundary + min-heap.
- Largest Rectangle in Histogram (LC 84) — same elevation-map shape, different question; stack of indices.
- Container With Most Water (LC 11) — pick two bars; greedy two-pointer.
Solve it now
Free. No sign-up. Python and JavaScript run instantly in your browser.
FAQ
Why does the two-pointer invariant work?
At any step, the lower side's water level is bounded by min(leftMax, rightMax). Since the lower side's running max is also <= the other side's running max (because the other side has at least one bar of higher height), we can safely fill water on the lower side using only its own running max.
Should I default to DP or two-pointer?
Code both if asked. Start with DP — it's easier to argue correctness. Two-pointer is the optimal answer; walk through the invariant carefully.
Free learning resources
Curated free links for this problem.
Practice these live with InterviewChamp.AI
Drill Trapping Rain Water and other Robinhood interview questions under real-loop conditions with instant feedback on your reasoning, complexity claims, and code.
Practice these live with InterviewChamp.AI →