Skip to content
Permalink

Comparing changes

This is a direct comparison between two commits made in this repository or its related repositories. View the default comparison for this range or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: trekhleb/javascript-algorithms
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 81bd8133a2860d5e9fb5a68f4cc003d9e140fa4b
Choose a base ref
..
head repository: trekhleb/javascript-algorithms
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 68f3f67fcc3ea68c1ba4207db19af6b68616d0a5
Choose a head ref
Showing with 38 additions and 6 deletions.
  1. +38 −6 src/algorithms/uncategorized/rain-terraces/dpRainTerraces.js
44 changes: 38 additions & 6 deletions src/algorithms/uncategorized/rain-terraces/dpRainTerraces.js
Original file line number Diff line number Diff line change
@@ -5,11 +5,43 @@
* @return {number}
*/
export default function dpRainTerraces(terraces) {
// Obtain the maximum elevations to the left and right of each terrace (inclusive).
const maxL = terraces.reduce((acc, val, idx) => [...acc, Math.max(val, (acc[idx - 1] || 0))], []);
const maxR = terraces.reduceRight((acc, val) => [Math.max(val, (acc[0] || 0)), ...acc], []);
let waterAmount = 0;

// Convert maximum values to amount of water at current index and sum water values.
const trap = terraces.map((val, idx) => Math.max(0, Math.min(maxL[idx], maxR[idx]) - val));
return trap.reduce((acc, val) => acc + val);
// Init arrays that will keep the list of left and right maximum levels for specific positions.
const leftMaxLevels = new Array(terraces.length).fill(0);
const rightMaxLevels = new Array(terraces.length).fill(0);

// 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],
);
}

// Calculate the highest terrace level from the RIGHT relative to the current terrace.
rightMaxLevels[terraces.length - 1] = terraces[terraces.length - 1];
for (let terraceIndex = terraces.length - 2; terraceIndex >= 0; terraceIndex -= 1) {
rightMaxLevels[terraceIndex] = Math.max(
terraces[terraceIndex],
rightMaxLevels[terraceIndex + 1],
);
}

// 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],
);

if (currentTerraceBoundary > terraces[terraceIndex]) {
waterAmount += currentTerraceBoundary - terraces[terraceIndex];
}
}

return waterAmount;
}