mirror of
https://github.moeyy.xyz/https://github.com/trekhleb/javascript-algorithms.git
synced 2024-12-26 15:11:16 +08:00
Add rain-terraces (trapping rain water) algorithm (#112)
* Add rain-terraces (trapping rain water) algorithm * Fixed linting errors * Fixed linting errors
This commit is contained in:
parent
97c9f6f303
commit
f142ca00b2
53
src/algorithms/uncategorized/rain-terraces/README.md
Normal file
53
src/algorithms/uncategorized/rain-terraces/README.md
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
# Rain Terraces (Trapping Rain Water) Problem
|
||||||
|
|
||||||
|
Given an array of non-negative integers representing terraces in an elevation map where the width of each bar is 1, compute how much water it is able to trap after raining.
|
||||||
|
|
||||||
|
![Rain Terraces](https://www.geeksforgeeks.org/wp-content/uploads/watertrap.png)
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
**Example #1**
|
||||||
|
|
||||||
|
```
|
||||||
|
Input: arr[] = [2, 0, 2]
|
||||||
|
Output: 2
|
||||||
|
Structure is like below
|
||||||
|
| |
|
||||||
|
|_|
|
||||||
|
We can trap 2 units of water in the middle gap.
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example #2**
|
||||||
|
|
||||||
|
```
|
||||||
|
Input: arr[] = [3, 0, 0, 2, 0, 4]
|
||||||
|
Output: 10
|
||||||
|
Structure is like below
|
||||||
|
|
|
||||||
|
| |
|
||||||
|
| | |
|
||||||
|
|__|_|
|
||||||
|
We can trap "3*2 units" of water between 3 an 2,
|
||||||
|
"1 unit" on top of bar 2 and "3 units" between 2
|
||||||
|
and 4. See below diagram also.
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example #3**
|
||||||
|
|
||||||
|
```
|
||||||
|
Input: arr[] = [0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1]
|
||||||
|
Output: 6
|
||||||
|
|
|
||||||
|
| || |
|
||||||
|
_|_||_||||||
|
||||||
|
Trap "1 unit" between first 1 and 2, "4 units" between
|
||||||
|
first 2 and 3 and "1 unit" between second last 1 and last 2
|
||||||
|
```
|
||||||
|
|
||||||
|
## Algorithms
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [GeeksForGeeks](https://www.geeksforgeeks.org/trapping-rain-water/)
|
77
src/algorithms/uncategorized/rain-terraces/rainTerraces.js
Normal file
77
src/algorithms/uncategorized/rain-terraces/rainTerraces.js
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
/**
|
||||||
|
* @param {number[]} terraces
|
||||||
|
* @return {number}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* STEPS
|
||||||
|
* 1. Find the highest terraces on the left and right side of the elevation map:
|
||||||
|
* e.g. [0, 2, 4, 3, 1, 2, 4, 0, 8, 7, 0] => (leftMax = 4, rightMax = 8)
|
||||||
|
* This is because water will "trail off" the sides of the terraces.
|
||||||
|
*
|
||||||
|
* 2. At this point, we are essentially dealing with a new map: [4, 3, 4, 2, 4, 0, 8].
|
||||||
|
* From here, we loop through the map from the left to the right (if leftMax > rightMax,
|
||||||
|
* otherwise we move from right to left), adding water as we go unless we reach a value
|
||||||
|
* that is greater than or equal to leftMax || rightMax.
|
||||||
|
* e.g. [4, 3, 4, 2, 4, 0, 8]
|
||||||
|
* ^
|
||||||
|
* water += leftMax - 3 => water = 1
|
||||||
|
* or if the terrace array was reversed:
|
||||||
|
* e.g. [8, 0, 4, 2, 4, 3, 4]
|
||||||
|
* ^
|
||||||
|
* water += rightMax - 3 => water = 1
|
||||||
|
*
|
||||||
|
* 3. Again, we've essentially shortened the map: [4, 2, 4, 0, 8].
|
||||||
|
* Now we repeat the above steps on the new array.
|
||||||
|
* e.g.
|
||||||
|
* Next Iteration:
|
||||||
|
* [4, 2, 4, 0, 8]
|
||||||
|
* ^
|
||||||
|
* water += leftMax - 2 => water = 3
|
||||||
|
*
|
||||||
|
* Next Iteration:
|
||||||
|
* [4, 0, 8]
|
||||||
|
* ^
|
||||||
|
* water += leftMax - 0 => water = 7
|
||||||
|
*
|
||||||
|
* return water(7)
|
||||||
|
*/
|
||||||
|
export default function rainTerraces(terraces) {
|
||||||
|
let start = 0;
|
||||||
|
let end = terraces.length - 1;
|
||||||
|
let water = 0;
|
||||||
|
let leftMax = 0;
|
||||||
|
let rightMax = 0;
|
||||||
|
|
||||||
|
while (start < end) {
|
||||||
|
// Loop to find left max
|
||||||
|
while (start < end && terraces[start] <= terraces[start + 1]) {
|
||||||
|
start += 1;
|
||||||
|
}
|
||||||
|
leftMax = terraces[start];
|
||||||
|
|
||||||
|
// Loop to find right max
|
||||||
|
while (end > start && terraces[end] <= terraces[end - 1]) {
|
||||||
|
end -= 1;
|
||||||
|
}
|
||||||
|
rightMax = terraces[end];
|
||||||
|
|
||||||
|
// Determine which direction we need to move in
|
||||||
|
if (leftMax < rightMax) {
|
||||||
|
// Move from left to right and collect water
|
||||||
|
start += 1;
|
||||||
|
while (start < end && terraces[start] <= leftMax) {
|
||||||
|
water += leftMax - terraces[start];
|
||||||
|
start += 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Move from left to right and collect water
|
||||||
|
end -= 1;
|
||||||
|
while (end > start && terraces[end] <= rightMax) {
|
||||||
|
water += rightMax - terraces[end];
|
||||||
|
end -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return water;
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
import rainTerraces from '../rainTerraces';
|
||||||
|
|
||||||
|
describe('rainTerraces', () => {
|
||||||
|
it('should find the amount of water collected after raining', () => {
|
||||||
|
expect(rainTerraces([2, 0, 2])).toBe(2);
|
||||||
|
expect(rainTerraces([3, 0, 0, 2, 0, 4])).toBe(10);
|
||||||
|
expect(rainTerraces([0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1])).toBe(6);
|
||||||
|
expect(rainTerraces([1, 1, 1, 1, 1])).toBe(0);
|
||||||
|
expect(rainTerraces([1, 2, 3, 4, 5])).toBe(0);
|
||||||
|
expect(rainTerraces([4, 1, 3, 1, 2, 1, 2, 1])).toBe(4);
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user