Files
codetutor/backend/data/questions/trapping-rain-water.yaml
2025-04-28 23:19:49 +01:00

130 lines
4.1 KiB
YAML

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