Skip to content

Commit 4ba5bdd

Browse files
committed
feat: add Trapping Rain Water
1 parent 9af84ee commit 4ba5bdd

File tree

7 files changed

+251
-1
lines changed

7 files changed

+251
-1
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
{
2+
"problem_name": "trapping_rain_water",
3+
"solution_class_name": "Solution",
4+
"problem_number": "42",
5+
"problem_title": "Trapping Rain Water",
6+
"difficulty": "Hard",
7+
"topics": "Array, Two Pointers, Dynamic Programming, Stack, Monotonic Stack",
8+
"tags": ["grind-75"],
9+
"readme_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.",
10+
"readme_examples": [
11+
{
12+
"content": "![Example 1](https://assets.leetcode.com/uploads/2018/10/22/rainwatertrap.png)\n\n```\nInput: height = [0,1,0,2,1,0,1,3,2,1,2,1]\nOutput: 6\n```\n**Explanation:** The above elevation map (black section) is represented by array [0,1,0,2,1,0,1,3,2,1,2,1]. In this case, 6 units of rain water (blue section) are being trapped."
13+
},
14+
{ "content": "```\nInput: height = [4,2,0,3,2,5]\nOutput: 9\n```" }
15+
],
16+
"readme_constraints": "- `n == height.length`\n- `1 <= n <= 2 * 10^4`\n- `0 <= height[i] <= 10^5`",
17+
"readme_additional": "",
18+
"solution_imports": "",
19+
"solution_methods": [
20+
{ "name": "trap", "parameters": "height: list[int]", "return_type": "int", "dummy_return": "0" }
21+
],
22+
"test_imports": "import pytest\nfrom leetcode_py.test_utils import logged_test\nfrom .solution import Solution",
23+
"test_class_name": "TrappingRainWater",
24+
"test_helper_methods": [
25+
{ "name": "setup_method", "parameters": "", "body": "self.solution = Solution()" }
26+
],
27+
"test_methods": [
28+
{
29+
"name": "test_trap",
30+
"parametrize": "height, expected",
31+
"parametrize_typed": "height: list[int], expected: int",
32+
"test_cases": "[([0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1], 6), ([4, 2, 0, 3, 2, 5], 9), ([3, 0, 2, 0, 4], 7), ([0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1], 6)]",
33+
"body": "result = self.solution.trap(height)\nassert result == expected"
34+
}
35+
],
36+
"playground_imports": "from solution import Solution",
37+
"playground_test_case": "# Example test case\nheight = [0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1]\nexpected = 6",
38+
"playground_execution": "result = Solution().trap(height)\nresult",
39+
"playground_assertion": "assert result == expected"
40+
}

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
PYTHON_VERSION = 3.13
2-
PROBLEM ?= largest_rectangle_in_histogram
2+
PROBLEM ?= trapping_rain_water
33
FORCE ?= 0
44
COMMA := ,
55

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Trapping Rain Water
2+
3+
**Difficulty:** Hard
4+
**Topics:** Array, Two Pointers, Dynamic Programming, Stack, Monotonic Stack
5+
**Tags:** grind-75
6+
7+
**LeetCode:** [Problem 42](https://leetcode.com/problems/trapping-rain-water/description/)
8+
9+
## Problem Description
10+
11+
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.
12+
13+
## Examples
14+
15+
### Example 1:
16+
17+
![Example 1](https://assets.leetcode.com/uploads/2018/10/22/rainwatertrap.png)
18+
19+
```
20+
Input: height = [0,1,0,2,1,0,1,3,2,1,2,1]
21+
Output: 6
22+
```
23+
24+
**Explanation:** The above elevation map (black section) is represented by array [0,1,0,2,1,0,1,3,2,1,2,1]. In this case, 6 units of rain water (blue section) are being trapped.
25+
26+
### Example 2:
27+
28+
```
29+
Input: height = [4,2,0,3,2,5]
30+
Output: 9
31+
```
32+
33+
## Constraints
34+
35+
- `n == height.length`
36+
- `1 <= n <= 2 * 10^4`
37+
- `0 <= height[i] <= 10^5`

leetcode/trapping_rain_water/__init__.py

Whitespace-only changes.
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "code",
5+
"execution_count": 1,
6+
"id": "imports",
7+
"metadata": {},
8+
"outputs": [],
9+
"source": [
10+
"from solution import Solution"
11+
]
12+
},
13+
{
14+
"cell_type": "code",
15+
"execution_count": 2,
16+
"id": "setup",
17+
"metadata": {},
18+
"outputs": [],
19+
"source": [
20+
"# Example test case\n",
21+
"height = [0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1]\n",
22+
"expected = 6"
23+
]
24+
},
25+
{
26+
"cell_type": "code",
27+
"execution_count": 3,
28+
"id": "execute",
29+
"metadata": {},
30+
"outputs": [
31+
{
32+
"data": {
33+
"text/plain": [
34+
"6"
35+
]
36+
},
37+
"execution_count": 3,
38+
"metadata": {},
39+
"output_type": "execute_result"
40+
}
41+
],
42+
"source": [
43+
"result = Solution().trap(height)\n",
44+
"result"
45+
]
46+
},
47+
{
48+
"cell_type": "code",
49+
"execution_count": 4,
50+
"id": "test",
51+
"metadata": {},
52+
"outputs": [],
53+
"source": [
54+
"assert result == expected"
55+
]
56+
}
57+
],
58+
"metadata": {
59+
"kernelspec": {
60+
"display_name": "leetcode-py-py3.13",
61+
"language": "python",
62+
"name": "python3"
63+
},
64+
"language_info": {
65+
"codemirror_mode": {
66+
"name": "ipython",
67+
"version": 3
68+
},
69+
"file_extension": ".py",
70+
"mimetype": "text/x-python",
71+
"name": "python",
72+
"nbconvert_exporter": "python",
73+
"pygments_lexer": "ipython3",
74+
"version": "3.13.7"
75+
}
76+
},
77+
"nbformat": 4,
78+
"nbformat_minor": 5
79+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# class Solution:
2+
# # Time: O(n)
3+
# # Space: O(1)
4+
# def trap(self, height: list[int]) -> int:
5+
# if not height:
6+
# return 0
7+
8+
# left, right = 0, len(height) - 1
9+
# left_max = right_max = water = 0
10+
11+
# while left < right:
12+
# if height[left] < height[right]:
13+
# if height[left] >= left_max:
14+
# left_max = height[left]
15+
# else:
16+
# water += left_max - height[left]
17+
# left += 1
18+
# else:
19+
# if height[right] >= right_max:
20+
# right_max = height[right]
21+
# else:
22+
# water += right_max - height[right]
23+
# right -= 1
24+
25+
# return water
26+
27+
28+
class Solution:
29+
# Time: O(n)
30+
# Space: O(1)
31+
def trap(self, height: list[int]) -> int:
32+
if not height:
33+
return 0
34+
35+
left, right = 0, len(height) - 1
36+
left_max = right_max = water = 0
37+
38+
while left < right:
39+
if height[left] < height[right]:
40+
if height[left] >= left_max:
41+
left_max = height[left]
42+
else:
43+
water += left_max - height[left]
44+
left += 1
45+
else:
46+
if height[right] >= right_max:
47+
right_max = height[right]
48+
else:
49+
water += right_max - height[right]
50+
right -= 1
51+
52+
return water
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import pytest
2+
3+
from leetcode_py.test_utils import logged_test
4+
5+
from .solution import Solution
6+
7+
8+
class TestTrappingRainWater:
9+
def setup_method(self):
10+
self.solution = Solution()
11+
12+
@pytest.mark.parametrize(
13+
"height, expected",
14+
[
15+
# Original examples
16+
([0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1], 6),
17+
([4, 2, 0, 3, 2, 5], 9),
18+
([3, 0, 2, 0, 4], 7),
19+
# Edge cases
20+
([], 0),
21+
([1], 0),
22+
([1, 2], 0),
23+
([2, 1], 0),
24+
# No water trapped
25+
([1, 2, 3, 4, 5], 0),
26+
([5, 4, 3, 2, 1], 0),
27+
# Simple cases
28+
([3, 0, 3], 3),
29+
([2, 1, 2], 1),
30+
([5, 2, 7, 2, 6, 1, 5, 3, 2, 4], 14),
31+
# All same height
32+
([3, 3, 3, 3], 0),
33+
# Valley pattern
34+
([3, 2, 1, 2, 3], 4),
35+
# Multiple peaks
36+
([0, 2, 0, 4, 0, 3, 0, 4, 0, 2, 0], 13),
37+
],
38+
)
39+
@logged_test
40+
def test_trap(self, height: list[int], expected: int):
41+
result = self.solution.trap(height)
42+
assert result == expected

0 commit comments

Comments
 (0)