Trapping Rain Water
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.
Example:
Input: height = [0,1,0,2,1,0,1,3,2,1,2,1]
Output: 6
Explanation: The above elevation map is represented by array [0,1,0,2,1,0,1,3,2,1,2,1]. In this case, 6 units of rain water are being trapped.
Visual Representation
Approach: Two Pointers
To calculate the amount of water trapped above any specific bar at index i, we need to know the highest bar to its left (maxLeft) and the highest bar to its right (maxRight).
The water trapped at i is determined by the formula:
Water[i] = min(maxLeft, maxRight) - height[i] (if this value is positive)
A common approach is to pre-compute two arrays: one storing the maxLeft for every index, and one storing the maxRight. However, this requires extra space. We can optimize this to space using Two Pointers.
Since the formula depends on min(maxLeft, maxRight), we donβt actually need to know both maximums. We only need to know whichever one is strictly smaller, because the smaller one acts as the bottleneck!
- Place
leftpointer at0andrightpointer at the end of the array. - Track the maximum heights seen so far from both sides:
maxLeft = height[left]andmaxRight = height[right]. - Initialize
trappedWater = 0. - While
left < right:- If
maxLeft < maxRight:- This means the water level at the
leftpointer is bottlenecked bymaxLeft. (Even if there are taller bars somewhere in the middle,maxLeftis the limiting factor). - Move
leftpointer inwards (left++). - Update
maxLeft = max(maxLeft, height[left]). - Add
maxLeft - height[left]totrappedWater.
- This means the water level at the
- Else (
maxRight <= maxLeft):- The water level at the
rightpointer is bottlenecked bymaxRight. - Move
rightpointer inwards (right--). - Update
maxRight = max(maxRight, height[right]). - Add
maxRight - height[right]totrappedWater.
- The water level at the
- If
- Return
trappedWater.
Solution
/**
* @param {number[]} height
* @return {number}
*/
function trap(height) {
if (!height || height.length === 0) return 0;
let left = 0;
let right = height.length - 1;
let maxLeft = height[left];
let maxRight = height[right];
let trappedWater = 0;
while (left < right) {
if (maxLeft < maxRight) {
left++;
maxLeft = Math.max(maxLeft, height[left]);
trappedWater += (maxLeft - height[left]);
} else {
right--;
maxRight = Math.max(maxRight, height[right]);
trappedWater += (maxRight - height[right]);
}
}
return trappedWater;
}
Complexity Analysis
- Time Complexity: where is the length of the
heightarray. Theleftandrightpointers move strictly inward towards each other, meaning each element in the array is evaluated exactly once. - Space Complexity: auxiliary space. Unlike the Dynamic Programming approach which requires arrays to store the left and right maxes, this solution only uses a few integer variables (
left,right,maxLeft,maxRight,trappedWater).