hard questions
This commit is contained in:
129
backend/data/questions/trapping-rain-water.yaml
Normal file
129
backend/data/questions/trapping-rain-water.yaml
Normal file
@@ -0,0 +1,129 @@
|
||||
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".
|
||||
Reference in New Issue
Block a user