title: Trapping Rain Water slug: trapping-rain-water difficulty: hard leetcode_id: 42 leetcode_url: https://leetcode.com/problems/trapping-rain-water/ categories: - arrays - two-pointers - stack patterns: - two-pointers - monotonic-stack description: | 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.length - 1 <= n <= 2 * 10^4 - 0 <= height[i] <= 10^5 examples: - input: "height = [0,1,0,2,1,0,1,3,2,1,2,1]" output: "6" explanation: "6 units of water are trapped between the bars." - input: "height = [4,2,0,3,2,5]" output: "9" explanation: "9 units of water are trapped." explanation: approach: | 1. Use two pointers from left and right 2. Track maximum height seen from each side 3. Move the pointer with smaller max height 4. Water at current position = max_height - current_height 5. Add to total and continue until pointers meet intuition: | Water at any position is determined by the minimum of the maximum heights to its left and right, minus the current height. With two pointers, we track left_max and right_max. If left_max < right_max, water at the left pointer is limited by left_max (the right side is guaranteed to be at least as tall). We process and move the pointer with the smaller maximum. common_pitfalls: - title: Only considering one side description: | Water level is determined by BOTH sides. You need to track maximum from left AND right. wrong_approach: "Only tracking left_max" correct_approach: "Track both left_max and right_max" - title: Counting bars instead of water description: | Water trapped at position i is max_height - height[i], not max_height. The bar itself takes up space. - title: Not updating max heights description: | Update left_max or right_max before calculating water, not after. key_takeaways: - Two pointers eliminate need for O(n) precomputation - Water level = min(left_max, right_max) - current_height - Always process the side with smaller max (guaranteed bound) - This can also be solved with monotonic stack or DP time_complexity: "O(n)" space_complexity: "O(1)" complexity_explanation: | Time: Single pass with two pointers. Space: Only a few variables for pointers and max values. solutions: - approach_name: Two Pointers (Optimal) is_optimal: true code: | def trap(height: list[int]) -> int: if not height: return 0 left, right = 0, len(height) - 1 left_max, right_max = 0, 0 water = 0 while left < right: if height[left] < height[right]: if height[left] >= left_max: left_max = height[left] else: water += left_max - height[left] left += 1 else: if height[right] >= right_max: right_max = height[right] else: water += right_max - height[right] right -= 1 return water explanation: | Process from both ends. Move the pointer with smaller max height. Add water based on the difference between max height and current height. - approach_name: Monotonic Stack is_optimal: false code: | def trap(height: list[int]) -> int: stack = [] # stores indices water = 0 for i, h in enumerate(height): while stack and h > height[stack[-1]]: top = stack.pop() if not stack: break width = i - stack[-1] - 1 bounded_height = min(h, height[stack[-1]]) - height[top] water += width * bounded_height stack.append(i) return water explanation: | Stack stores indices of bars in decreasing height order. When a taller bar is found, calculate water trapped in the "valley".