mirror of
https://github.moeyy.xyz/https://github.com/trekhleb/javascript-algorithms.git
synced 2024-12-26 23:21:18 +08:00
Add Rain Terraces problem.
This commit is contained in:
parent
3271ee92b9
commit
6fc429975f
@ -128,6 +128,7 @@ a set of rules that precisely define a sequence of operations.
|
|||||||
* `B` [Square Matrix Rotation](src/algorithms/uncategorized/square-matrix-rotation) - in-place algorithm
|
* `B` [Square Matrix Rotation](src/algorithms/uncategorized/square-matrix-rotation) - in-place algorithm
|
||||||
* `B` [Jump Game](src/algorithms/uncategorized/jump-game) - backtracking, dynamic programming (top-down + bottom-up) and greedy examples
|
* `B` [Jump Game](src/algorithms/uncategorized/jump-game) - backtracking, dynamic programming (top-down + bottom-up) and greedy examples
|
||||||
* `B` [Unique Paths](src/algorithms/uncategorized/unique-paths) - backtracking, dynamic programming and Pascal's Triangle based examples
|
* `B` [Unique Paths](src/algorithms/uncategorized/unique-paths) - backtracking, dynamic programming and Pascal's Triangle based examples
|
||||||
|
* `B` [Rain Terraces](src/algorithms/uncategorized/rain-terraces) - trapping rain water problem
|
||||||
* `A` [N-Queens Problem](src/algorithms/uncategorized/n-queens)
|
* `A` [N-Queens Problem](src/algorithms/uncategorized/n-queens)
|
||||||
* `A` [Knight's Tour](src/algorithms/uncategorized/knight-tour)
|
* `A` [Knight's Tour](src/algorithms/uncategorized/knight-tour)
|
||||||
|
|
||||||
|
@ -2,11 +2,20 @@ import rainTerraces from '../rainTerraces';
|
|||||||
|
|
||||||
describe('rainTerraces', () => {
|
describe('rainTerraces', () => {
|
||||||
it('should find the amount of water collected after raining', () => {
|
it('should find the amount of water collected after raining', () => {
|
||||||
|
expect(rainTerraces([1])).toBe(0);
|
||||||
|
expect(rainTerraces([1, 0])).toBe(0);
|
||||||
|
expect(rainTerraces([0, 1])).toBe(0);
|
||||||
|
expect(rainTerraces([0, 1, 0])).toBe(0);
|
||||||
|
expect(rainTerraces([0, 1, 0, 0])).toBe(0);
|
||||||
|
expect(rainTerraces([0, 1, 0, 0, 1, 0])).toBe(2);
|
||||||
|
expect(rainTerraces([0, 2, 0, 0, 1, 0])).toBe(2);
|
||||||
expect(rainTerraces([2, 0, 2])).toBe(2);
|
expect(rainTerraces([2, 0, 2])).toBe(2);
|
||||||
|
expect(rainTerraces([2, 0, 5])).toBe(2);
|
||||||
expect(rainTerraces([3, 0, 0, 2, 0, 4])).toBe(10);
|
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([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, 1, 1, 1, 1])).toBe(0);
|
||||||
expect(rainTerraces([1, 2, 3, 4, 5])).toBe(0);
|
expect(rainTerraces([1, 2, 3, 4, 5])).toBe(0);
|
||||||
expect(rainTerraces([4, 1, 3, 1, 2, 1, 2, 1])).toBe(4);
|
expect(rainTerraces([4, 1, 3, 1, 2, 1, 2, 1])).toBe(4);
|
||||||
|
expect(rainTerraces([0, 2, 4, 3, 4, 2, 4, 0, 8, 7, 0])).toBe(7);
|
||||||
});
|
});
|
||||||
});
|
});
|
@ -2,76 +2,84 @@
|
|||||||
* @param {number[]} terraces
|
* @param {number[]} terraces
|
||||||
* @return {number}
|
* @return {number}
|
||||||
*/
|
*/
|
||||||
|
export default function rainTerraces(terraces) {
|
||||||
/*
|
/*
|
||||||
* STEPS
|
* STEPS
|
||||||
|
*
|
||||||
* 1. Find the highest terraces on the left and right side of the elevation map:
|
* 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)
|
* e.g. for [0, 2, 4, 3, 4, 2, 4, 0, 8, 7, 0] we would have leftMax = 4 and rightMax = 8.
|
||||||
* This is because water will "trail off" the sides of the terraces.
|
* 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].
|
* 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,
|
* 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
|
* (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.
|
* that is greater than or equal to leftMax or rightMax.
|
||||||
* e.g. [4, 3, 4, 2, 4, 0, 8]
|
* e.g. [4, 3, 4, 2, 4, 0, 8]
|
||||||
* ^
|
* ^
|
||||||
* water += leftMax - 3 => water = 1
|
* water = water + (leftMax - 3) = 1
|
||||||
|
*
|
||||||
* or if the terrace array was reversed:
|
* or if the terrace array was reversed:
|
||||||
* e.g. [8, 0, 4, 2, 4, 3, 4]
|
* e.g. [8, 0, 4, 2, 4, 3, 4]
|
||||||
* ^
|
* ^
|
||||||
* water += rightMax - 3 => water = 1
|
* water = water + (rightMax - 3) = 1
|
||||||
*
|
*
|
||||||
* 3. Again, we've essentially shortened the map: [4, 2, 4, 0, 8].
|
* 3. Again, we've essentially shortened the map: [4, 2, 4, 0, 8].
|
||||||
* Now we repeat the above steps on the new array.
|
* Now we repeat the above steps on the new array.
|
||||||
* e.g.
|
*
|
||||||
* Next Iteration:
|
* Next Iteration:
|
||||||
* [4, 2, 4, 0, 8]
|
* [4, 2, 4, 0, 8]
|
||||||
* ^
|
* ^
|
||||||
* water += leftMax - 2 => water = 3
|
* water = water + (leftMax - 2) = 3
|
||||||
*
|
*
|
||||||
* Next Iteration:
|
* Next Iteration:
|
||||||
* [4, 0, 8]
|
* [4, 0, 8]
|
||||||
* ^
|
* ^
|
||||||
* water += leftMax - 0 => water = 7
|
* water = water + (leftMax - 0) = 7
|
||||||
*
|
*
|
||||||
* return water(7)
|
* 4. Return result: 7
|
||||||
*/
|
*/
|
||||||
export default function rainTerraces(terraces) {
|
let leftIndex = 0;
|
||||||
let start = 0;
|
let rightIndex = terraces.length - 1;
|
||||||
let end = terraces.length - 1;
|
|
||||||
let water = 0;
|
|
||||||
let leftMax = 0;
|
|
||||||
let rightMax = 0;
|
|
||||||
|
|
||||||
while (start < end) {
|
let leftMaxLevel = 0;
|
||||||
// Loop to find left max
|
let rightMaxLevel = 0;
|
||||||
while (start < end && terraces[start] <= terraces[start + 1]) {
|
|
||||||
start += 1;
|
let waterAmount = 0;
|
||||||
|
|
||||||
|
while (leftIndex < rightIndex) {
|
||||||
|
// Loop to find the highest terrace from the left side.
|
||||||
|
while (leftIndex < rightIndex && terraces[leftIndex] <= terraces[leftIndex + 1]) {
|
||||||
|
leftIndex += 1;
|
||||||
}
|
}
|
||||||
leftMax = terraces[start];
|
|
||||||
|
|
||||||
// Loop to find right max
|
leftMaxLevel = terraces[leftIndex];
|
||||||
while (end > start && terraces[end] <= terraces[end - 1]) {
|
|
||||||
end -= 1;
|
// Loop to find the highest terrace from the right side.
|
||||||
|
while (rightIndex > leftIndex && terraces[rightIndex] <= terraces[rightIndex - 1]) {
|
||||||
|
rightIndex -= 1;
|
||||||
}
|
}
|
||||||
rightMax = terraces[end];
|
|
||||||
|
|
||||||
// Determine which direction we need to move in
|
rightMaxLevel = terraces[rightIndex];
|
||||||
if (leftMax < rightMax) {
|
|
||||||
// Move from left to right and collect water
|
// Determine which direction we need to go.
|
||||||
start += 1;
|
if (leftMaxLevel < rightMaxLevel) {
|
||||||
while (start < end && terraces[start] <= leftMax) {
|
// Move from left to right and collect water.
|
||||||
water += leftMax - terraces[start];
|
leftIndex += 1;
|
||||||
start += 1;
|
|
||||||
|
while (leftIndex < rightIndex && terraces[leftIndex] <= leftMaxLevel) {
|
||||||
|
waterAmount += leftMaxLevel - terraces[leftIndex];
|
||||||
|
leftIndex += 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Move from left to right and collect water
|
// Move from right to left and collect water.
|
||||||
end -= 1;
|
rightIndex -= 1;
|
||||||
while (end > start && terraces[end] <= rightMax) {
|
|
||||||
water += rightMax - terraces[end];
|
while (leftIndex < rightIndex && terraces[rightIndex] <= rightMaxLevel) {
|
||||||
end -= 1;
|
waterAmount += rightMaxLevel - terraces[rightIndex];
|
||||||
|
rightIndex -= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return water;
|
|
||||||
|
return waterAmount;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user