Skip to content

Commit 340a71b

Browse files
committed
Add brute force solution of Rain Terraces problem.
1 parent 6fc4299 commit 340a71b

File tree

7 files changed

+131
-31
lines changed

7 files changed

+131
-31
lines changed

‎README.md‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ a set of rules that precisely define a sequence of operations.
128128
*`B`[Square Matrix Rotation](src/algorithms/uncategorized/square-matrix-rotation) - in-place algorithm
129129
*`B`[Jump Game](src/algorithms/uncategorized/jump-game) - backtracking, dynamic programming (top-down + bottom-up) and greedy examples
130130
*`B`[Unique Paths](src/algorithms/uncategorized/unique-paths) - backtracking, dynamic programming and Pascal's Triangle based examples
131-
*`B`[Rain Terraces](src/algorithms/uncategorized/rain-terraces) - trapping rain water problem
131+
*`B`[Rain Terraces](src/algorithms/uncategorized/rain-terraces) - trapping rain water problem (dynamic programming and brute force versions)
132132
*`A`[N-Queens Problem](src/algorithms/uncategorized/n-queens)
133133
*`A`[Knight's Tour](src/algorithms/uncategorized/knight-tour)
134134

@@ -140,6 +140,7 @@ algorithm is an abstraction higher than a computer program.
140140

141141
***Brute Force** - look at all the possibilities and selects the best solution
142142
*`B`[Linear Search](src/algorithms/search/linear-search)
143+
*`B`[Rain Terraces](src/algorithms/uncategorized/rain-terraces) - trapping rain water problem
143144
*`A`[Maximum Subarray](src/algorithms/sets/maximum-subarray)
144145
*`A`[Travelling Salesman Problem](src/algorithms/graph/travelling-salesman) - shortest possible route that visits each city and returns to the origin city
145146
***Greedy** - choose the best option at the current time, without any consideration for the future
@@ -164,6 +165,7 @@ algorithm is an abstraction higher than a computer program.
164165
*`B`[Fibonacci Number](src/algorithms/math/fibonacci)
165166
*`B`[Jump Game](src/algorithms/uncategorized/jump-game)
166167
*`B`[Unique Paths](src/algorithms/uncategorized/unique-paths)
168+
*`B`[Rain Terraces](src/algorithms/uncategorized/rain-terraces) - trapping rain water problem
167169
*`A`[Levenshtein Distance](src/algorithms/string/levenshtein-distance) - minimum edit distance between two sequences
168170
*`A`[Longest Common Subsequence](src/algorithms/sets/longest-common-subsequence) (LCS)
169171
*`A`[Longest Common Substring](src/algorithms/string/longest-common-substring)

‎src/algorithms/uncategorized/rain-terraces/README.md‎

Lines changed: 50 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -62,16 +62,58 @@ be stored in every element of array. For example, consider the array
6262
`[3, 0, 0, 2, 0, 4]`, We can trap "3*2 units" of water between 3 an 2, "1 unit"
6363
on top of bar 2 and "3 units" between 2 and 4. See below diagram also.
6464

65-
A **simple solution** is to traverse every array element and find the highest
66-
bars on left and right sides. Take the smaller of two heights. The difference
67-
between smaller height and height of current element is the amount of water
68-
that can be stored in this array element. Time complexity of this solution
69-
is `O(n2)`.
65+
### Approach 1: Brute force
7066

71-
An **efficient solution** is to pre-compute highest bar on left and right of
72-
every bar in `O(n)` time. Then use these pre-computed values to find the
73-
amount of water in every array element.
67+
**Intuition**
68+
69+
For each element in the array, we find the maximum level of water it can trap
70+
after the rain, which is equal to the minimum of maximum height of bars on both
71+
the sides minus its own height.
72+
73+
**Steps**
74+
75+
- Initialize `answer = 0`
76+
- Iterate the array from left to right:
77+
- Initialize `max_left = 0 and `max_right = 0`
78+
- Iterate from the current element to the beginning of array updating: `max_left = max(max_left, height[j])`
79+
- Iterate from the current element to the end of array updating: `max_right = max(max_right, height[j])`
80+
- Add `min(max_left, max_right) − height[i]` to `answer`
81+
82+
**Complexity Analysis**
83+
84+
Time complexity: `O(n^2)`. For each element of array, we iterate the left and right parts.
85+
86+
Auxiliary space complexity: `O(1)` extra space.
87+
88+
### Approach 2: Dynamic Programming
89+
90+
**Intuition**
91+
92+
In brute force, we iterate over the left and right parts again and again just to
93+
find the highest bar size up to that index. But, this could be stored. Voila,
94+
dynamic programming.
95+
96+
So we may pre-compute highest bar on left and right of every bar in `O(n)` time.
97+
Then use these pre-computed values to find the amount of water in every array element.
98+
99+
The concept is illustrated as shown:
100+
101+
![DP Trapping Rain Water](https://leetcode.com/problems/trapping-rain-water/Figures/42/trapping_rain_water.png)
102+
103+
**Steps**
104+
105+
- Find maximum height of bar from the left end up to an index `i` in the array `left_max`.
106+
- Find maximum height of bar from the right end up to an index `i` in the array `right_max`.
107+
- Iterate over the `height` array and update `answer`:
108+
- Add `min(max_left[i], max_right[i]) − height[i]` to `answer`.
109+
110+
**Complexity Analysis**
111+
112+
Time complexity: `O(n)`.
113+
114+
Auxiliary space complexity: `O(n)` extra space.
74115

75116
## References
76117

77118
-[GeeksForGeeks](https://www.geeksforgeeks.org/trapping-rain-water/)
119+
-[LeetCode](https://leetcode.com/problems/trapping-rain-water/solution/)
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
importbfRainTerracesfrom'../bfRainTerraces';
2+
3+
describe('bfRainTerraces',()=>{
4+
it('should find the amount of water collected after raining',()=>{
5+
expect(bfRainTerraces([1])).toBe(0);
6+
expect(bfRainTerraces([1,0])).toBe(0);
7+
expect(bfRainTerraces([0,1])).toBe(0);
8+
expect(bfRainTerraces([0,1,0])).toBe(0);
9+
expect(bfRainTerraces([0,1,0,0])).toBe(0);
10+
expect(bfRainTerraces([0,1,0,0,1,0])).toBe(2);
11+
expect(bfRainTerraces([0,2,0,0,1,0])).toBe(2);
12+
expect(bfRainTerraces([2,0,2])).toBe(2);
13+
expect(bfRainTerraces([2,0,5])).toBe(2);
14+
expect(bfRainTerraces([3,0,0,2,0,4])).toBe(10);
15+
expect(bfRainTerraces([0,1,0,2,1,0,1,3,2,1,2,1])).toBe(6);
16+
expect(bfRainTerraces([1,1,1,1,1])).toBe(0);
17+
expect(bfRainTerraces([1,2,3,4,5])).toBe(0);
18+
expect(bfRainTerraces([4,1,3,1,2,1,2,1])).toBe(4);
19+
expect(bfRainTerraces([0,2,4,3,4,2,4,0,8,7,0])).toBe(7);
20+
});
21+
});
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
importdpRainTerracesfrom'../dpRainTerraces';
2+
3+
describe('dpRainTerraces',()=>{
4+
it('should find the amount of water collected after raining',()=>{
5+
expect(dpRainTerraces([1])).toBe(0);
6+
expect(dpRainTerraces([1,0])).toBe(0);
7+
expect(dpRainTerraces([0,1])).toBe(0);
8+
expect(dpRainTerraces([0,1,0])).toBe(0);
9+
expect(dpRainTerraces([0,1,0,0])).toBe(0);
10+
expect(dpRainTerraces([0,1,0,0,1,0])).toBe(2);
11+
expect(dpRainTerraces([0,2,0,0,1,0])).toBe(2);
12+
expect(dpRainTerraces([2,0,2])).toBe(2);
13+
expect(dpRainTerraces([2,0,5])).toBe(2);
14+
expect(dpRainTerraces([3,0,0,2,0,4])).toBe(10);
15+
expect(dpRainTerraces([0,1,0,2,1,0,1,3,2,1,2,1])).toBe(6);
16+
expect(dpRainTerraces([1,1,1,1,1])).toBe(0);
17+
expect(dpRainTerraces([1,2,3,4,5])).toBe(0);
18+
expect(dpRainTerraces([4,1,3,1,2,1,2,1])).toBe(4);
19+
expect(dpRainTerraces([0,2,4,3,4,2,4,0,8,7,0])).toBe(7);
20+
});
21+
});

‎src/algorithms/uncategorized/rain-terraces/__test__/rainTerraces.test.js‎

Lines changed: 0 additions & 21 deletions
This file was deleted.
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/**
2+
* BRUTE FORCE approach of solving Trapping Rain Water problem.
3+
*
4+
* @param{number[]} terraces
5+
* @return{number}
6+
*/
7+
exportdefaultfunctionbfRainTerraces(terraces){
8+
letwaterAmount=0;
9+
10+
for(letterraceIndex=0;terraceIndex<terraces.length;terraceIndex+=1){
11+
// Get left most high terrace.
12+
letleftHighestLevel=0;
13+
for(letleftIndex=terraceIndex-1;leftIndex>=0;leftIndex-=1){
14+
leftHighestLevel=Math.max(leftHighestLevel,terraces[leftIndex]);
15+
}
16+
17+
// Get right most high terrace.
18+
letrightHighestLevel=0;
19+
for(letrightIndex=terraceIndex+1;rightIndex<terraces.length;rightIndex+=1){
20+
rightHighestLevel=Math.max(rightHighestLevel,terraces[rightIndex]);
21+
}
22+
23+
// Add current terrace water amount.
24+
constterraceBoundaryLevel=Math.min(leftHighestLevel,rightHighestLevel);
25+
if(terraceBoundaryLevel>terraces[terraceIndex]){
26+
// Terrace will be able to store the water if the lowest of two left and right highest
27+
// terraces are still higher than the current one.
28+
waterAmount+=Math.min(leftHighestLevel,rightHighestLevel)-terraces[terraceIndex];
29+
}
30+
}
31+
32+
returnwaterAmount;
33+
}

src/algorithms/uncategorized/rain-terraces/rainTerraces.js renamed to src/algorithms/uncategorized/rain-terraces/dpRainTerraces.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
/**
2+
* DYNAMIC PROGRAMMING approach of solving Trapping Rain Water problem.
3+
*
24
* @param{number[]} terraces
35
* @return{number}
46
*/
5-
exportdefaultfunctionrainTerraces(terraces){
7+
exportdefaultfunctiondpRainTerraces(terraces){
68
/*
79
* STEPS
810
*

0 commit comments

Comments
(0)