mirror of
https://github.moeyy.xyz/https://github.com/trekhleb/javascript-algorithms.git
synced 2024-12-26 23:21:18 +08:00
Refactor dynamic programming approach of Trapping Rain Water problem.
This commit is contained in:
parent
340a71b7d9
commit
f07e96ec59
@ -5,81 +5,41 @@
|
|||||||
* @return {number}
|
* @return {number}
|
||||||
*/
|
*/
|
||||||
export default function dpRainTerraces(terraces) {
|
export default function dpRainTerraces(terraces) {
|
||||||
/*
|
|
||||||
* STEPS
|
|
||||||
*
|
|
||||||
* 1. Find the highest terraces on the left and right side of the elevation map:
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* 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 or rightMax.
|
|
||||||
* e.g. [4, 3, 4, 2, 4, 0, 8]
|
|
||||||
* ^
|
|
||||||
* water = water + (leftMax - 3) = 1
|
|
||||||
*
|
|
||||||
* or if the terrace array was reversed:
|
|
||||||
* e.g. [8, 0, 4, 2, 4, 3, 4]
|
|
||||||
* ^
|
|
||||||
* water = water + (rightMax - 3) = 1
|
|
||||||
*
|
|
||||||
* 3. Again, we've essentially shortened the map: [4, 2, 4, 0, 8].
|
|
||||||
* Now we repeat the above steps on the new array.
|
|
||||||
*
|
|
||||||
* Next Iteration:
|
|
||||||
* [4, 2, 4, 0, 8]
|
|
||||||
* ^
|
|
||||||
* water = water + (leftMax - 2) = 3
|
|
||||||
*
|
|
||||||
* Next Iteration:
|
|
||||||
* [4, 0, 8]
|
|
||||||
* ^
|
|
||||||
* water = water + (leftMax - 0) = 7
|
|
||||||
*
|
|
||||||
* 4. Return result: 7
|
|
||||||
*/
|
|
||||||
let leftIndex = 0;
|
|
||||||
let rightIndex = terraces.length - 1;
|
|
||||||
|
|
||||||
let leftMaxLevel = 0;
|
|
||||||
let rightMaxLevel = 0;
|
|
||||||
|
|
||||||
let waterAmount = 0;
|
let waterAmount = 0;
|
||||||
|
|
||||||
while (leftIndex < rightIndex) {
|
// Init arrays that will keep the list of left and right maximum levels for specific positions.
|
||||||
// Loop to find the highest terrace from the left side.
|
const leftMaxLevels = new Array(terraces.length).fill(0);
|
||||||
while (leftIndex < rightIndex && terraces[leftIndex] <= terraces[leftIndex + 1]) {
|
const rightMaxLevels = new Array(terraces.length).fill(0);
|
||||||
leftIndex += 1;
|
|
||||||
|
// Calculate the highest terrace level from the LEFT relative to the current terrace.
|
||||||
|
[leftMaxLevels[0]] = terraces;
|
||||||
|
for (let terraceIndex = 1; terraceIndex < terraces.length; terraceIndex += 1) {
|
||||||
|
leftMaxLevels[terraceIndex] = Math.max(
|
||||||
|
terraces[terraceIndex],
|
||||||
|
leftMaxLevels[terraceIndex - 1],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
leftMaxLevel = terraces[leftIndex];
|
// Calculate the highest terrace level from the RIGHT relative to the current terrace.
|
||||||
|
rightMaxLevels[terraces.length - 1] = terraces[terraces.length - 1];
|
||||||
// Loop to find the highest terrace from the right side.
|
for (let terraceIndex = terraces.length - 2; terraceIndex >= 0; terraceIndex -= 1) {
|
||||||
while (rightIndex > leftIndex && terraces[rightIndex] <= terraces[rightIndex - 1]) {
|
rightMaxLevels[terraceIndex] = Math.max(
|
||||||
rightIndex -= 1;
|
terraces[terraceIndex],
|
||||||
|
rightMaxLevels[terraceIndex + 1],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
rightMaxLevel = terraces[rightIndex];
|
// Not let's go through all terraces one by one and calculate how much water
|
||||||
|
// each terrace may accumulate based on previously calculated values.
|
||||||
|
for (let terraceIndex = 0; terraceIndex < terraces.length; terraceIndex += 1) {
|
||||||
|
// Pick the lowest from the left/right highest terraces.
|
||||||
|
const currentTerraceBoundary = Math.min(
|
||||||
|
leftMaxLevels[terraceIndex],
|
||||||
|
rightMaxLevels[terraceIndex],
|
||||||
|
);
|
||||||
|
|
||||||
// Determine which direction we need to go.
|
if (currentTerraceBoundary > terraces[terraceIndex]) {
|
||||||
if (leftMaxLevel < rightMaxLevel) {
|
waterAmount += currentTerraceBoundary - terraces[terraceIndex];
|
||||||
// Move from left to right and collect water.
|
|
||||||
leftIndex += 1;
|
|
||||||
|
|
||||||
while (leftIndex < rightIndex && terraces[leftIndex] <= leftMaxLevel) {
|
|
||||||
waterAmount += leftMaxLevel - terraces[leftIndex];
|
|
||||||
leftIndex += 1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Move from right to left and collect water.
|
|
||||||
rightIndex -= 1;
|
|
||||||
|
|
||||||
while (leftIndex < rightIndex && terraces[rightIndex] <= rightMaxLevel) {
|
|
||||||
waterAmount += rightMaxLevel - terraces[rightIndex];
|
|
||||||
rightIndex -= 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user