|
5 | 5 | * @return {number}
|
6 | 6 | */
|
7 | 7 | export default function dpRainTerraces(terraces) {
|
8 |
| - /* |
9 |
| - * STEPS |
10 |
| - * |
11 |
| - * 1. Find the highest terraces on the left and right side of the elevation map: |
12 |
| - * e.g. for [0, 2, 4, 3, 4, 2, 4, 0, 8, 7, 0] we would have leftMax = 4 and rightMax = 8. |
13 |
| - * This is because water will "trail off" the sides of the terraces. |
14 |
| - * |
15 |
| - * 2. At this point, we are essentially dealing with a new map: [4, 3, 4, 2, 4, 0, 8]. |
16 |
| - * From here, we loop through the map from the left to the right if leftMax < rightMax |
17 |
| - * (otherwise we move from right to left), adding water as we go unless we reach a value |
18 |
| - * that is greater than or equal to leftMax or rightMax. |
19 |
| - * e.g. [4, 3, 4, 2, 4, 0, 8] |
20 |
| - * ^ |
21 |
| - * water = water + (leftMax - 3) = 1 |
22 |
| - * |
23 |
| - * or if the terrace array was reversed: |
24 |
| - * e.g. [8, 0, 4, 2, 4, 3, 4] |
25 |
| - * ^ |
26 |
| - * water = water + (rightMax - 3) = 1 |
27 |
| - * |
28 |
| - * 3. Again, we've essentially shortened the map: [4, 2, 4, 0, 8]. |
29 |
| - * Now we repeat the above steps on the new array. |
30 |
| - * |
31 |
| - * Next Iteration: |
32 |
| - * [4, 2, 4, 0, 8] |
33 |
| - * ^ |
34 |
| - * water = water + (leftMax - 2) = 3 |
35 |
| - * |
36 |
| - * Next Iteration: |
37 |
| - * [4, 0, 8] |
38 |
| - * ^ |
39 |
| - * water = water + (leftMax - 0) = 7 |
40 |
| - * |
41 |
| - * 4. Return result: 7 |
42 |
| - */ |
43 |
| - let leftIndex = 0; |
44 |
| - let rightIndex = terraces.length - 1; |
45 |
| - |
46 |
| - let leftMaxLevel = 0; |
47 |
| - let rightMaxLevel = 0; |
48 |
| - |
49 | 8 | let waterAmount = 0;
|
50 | 9 |
|
51 |
| - while (leftIndex < rightIndex) { |
52 |
| - // Loop to find the highest terrace from the left side. |
53 |
| - while (leftIndex < rightIndex && terraces[leftIndex] <= terraces[leftIndex + 1]) { |
54 |
| - leftIndex += 1; |
55 |
| - } |
56 |
| - |
57 |
| - leftMaxLevel = terraces[leftIndex]; |
58 |
| - |
59 |
| - // Loop to find the highest terrace from the right side. |
60 |
| - while (rightIndex > leftIndex && terraces[rightIndex] <= terraces[rightIndex - 1]) { |
61 |
| - rightIndex -= 1; |
62 |
| - } |
63 |
| - |
64 |
| - rightMaxLevel = terraces[rightIndex]; |
65 |
| - |
66 |
| - // Determine which direction we need to go. |
67 |
| - if (leftMaxLevel < rightMaxLevel) { |
68 |
| - // Move from left to right and collect water. |
69 |
| - leftIndex += 1; |
| 10 | + // Init arrays that will keep the list of left and right maximum levels for specific positions. |
| 11 | + const leftMaxLevels = new Array(terraces.length).fill(0); |
| 12 | + const rightMaxLevels = new Array(terraces.length).fill(0); |
| 13 | + |
| 14 | + // Calculate the highest terrace level from the LEFT relative to the current terrace. |
| 15 | + [leftMaxLevels[0]] = terraces; |
| 16 | + for (let terraceIndex = 1; terraceIndex < terraces.length; terraceIndex += 1) { |
| 17 | + leftMaxLevels[terraceIndex] = Math.max( |
| 18 | + terraces[terraceIndex], |
| 19 | + leftMaxLevels[terraceIndex - 1], |
| 20 | + ); |
| 21 | + } |
70 | 22 |
|
71 |
| - while (leftIndex < rightIndex && terraces[leftIndex] <= leftMaxLevel) { |
72 |
| - waterAmount += leftMaxLevel - terraces[leftIndex]; |
73 |
| - leftIndex += 1; |
74 |
| - } |
75 |
| - } else { |
76 |
| - // Move from right to left and collect water. |
77 |
| - rightIndex -= 1; |
| 23 | + // Calculate the highest terrace level from the RIGHT relative to the current terrace. |
| 24 | + rightMaxLevels[terraces.length - 1] = terraces[terraces.length - 1]; |
| 25 | + for (let terraceIndex = terraces.length - 2; terraceIndex >= 0; terraceIndex -= 1) { |
| 26 | + rightMaxLevels[terraceIndex] = Math.max( |
| 27 | + terraces[terraceIndex], |
| 28 | + rightMaxLevels[terraceIndex + 1], |
| 29 | + ); |
| 30 | + } |
78 | 31 |
|
79 |
| - while (leftIndex < rightIndex && terraces[rightIndex] <= rightMaxLevel) { |
80 |
| - waterAmount += rightMaxLevel - terraces[rightIndex]; |
81 |
| - rightIndex -= 1; |
82 |
| - } |
| 32 | + // Not let's go through all terraces one by one and calculate how much water |
| 33 | + // each terrace may accumulate based on previously calculated values. |
| 34 | + for (let terraceIndex = 0; terraceIndex < terraces.length; terraceIndex += 1) { |
| 35 | + // Pick the lowest from the left/right highest terraces. |
| 36 | + const currentTerraceBoundary = Math.min( |
| 37 | + leftMaxLevels[terraceIndex], |
| 38 | + rightMaxLevels[terraceIndex], |
| 39 | + ); |
| 40 | + |
| 41 | + if (currentTerraceBoundary > terraces[terraceIndex]) { |
| 42 | + waterAmount += currentTerraceBoundary - terraces[terraceIndex]; |
83 | 43 | }
|
84 | 44 | }
|
85 | 45 |
|
|
0 commit comments