|
| 1 | +// Runtime: 1 ms (Top 95.15%) | Memory: 41.70 MB (Top 26.54%) |
| 2 | + |
1 | 3 | class Solution {
|
2 |
| - public int mctFromLeafValues(int[] arr) { |
3 |
| - |
4 |
| - int sum = 0; |
5 |
| - Stack<Integer> stack = new Stack<>(); |
6 |
| - for (int num: arr) { |
7 |
| - sum += cleanUpStack(num, stack); |
8 |
| - } |
9 |
| - sum += cleanUpStack(17, stack); |
10 |
| - |
11 |
| - return sum; |
12 |
| - } |
| 4 | + // Use stack. Similar to trapping the rain water problem and the largest rectangle under histogram |
| 5 | + // Use stack to keep a decreasing order by adding smaller values, while there is bigger value |
| 6 | + //arr[i] than the peek, pop it and store as mid and calculate the multiplication mid*min(arr[i], |
| 7 | + //stack.peek()). |
| 8 | + |
| 9 | + // NOTE: if we observe the number array, in order to obtain the smallest sum of all non-leaf |
| 10 | + // values, we want to merge those small values first. In order words, the smaller a value |
| 11 | + // is, the lower leaf it should stay because this way as we are building the tree up, |
| 12 | + // we are building smaller multiplication/parent node first as it is only going to get bigger |
| 13 | + // as we build the tree up. |
13 | 14 |
|
14 |
| - private int cleanUpStack(int target, Stack<Integer> stack) { |
15 |
| - int last = 0; |
16 |
| - int sum = 0; |
17 |
| - while (!stack.isEmpty() && stack.peek() <= target) { |
18 |
| - int cur = stack.pop(); |
19 |
| - sum += last * cur; |
20 |
| - last = cur; |
21 |
| - } |
22 |
| - if (target != 17) { |
23 |
| - sum += target * last; |
24 |
| - stack.push(target); |
25 |
| - } |
26 |
| - return sum; |
| 15 | + // Ex: 4 3 2 1 5 |
| 16 | + // There are many ways we can build a tree following the problem's requirement. However, to |
| 17 | + // gain smallest sum. We need to merge 2 and 1 first as they are the two smallest ones. To |
| 18 | + // do that, we use the stack mentioned above as a decreasing order. After |
| 19 | + // that we get a parent node with value 2. This node could be a left or right child of its parent |
| 20 | + // but what we want is that its parent needs also be as small as possible. We also know that its |
| 21 | + // parent has one mutiplier already: 2. Note: this 2 is not from the product of 1 * 2, but from the max of child |
| 22 | + // 1 and 2 as the problem requires. So, we see what values next to the leaf 2 could be a |
| 23 | + // candidate. Obviously, 3 since it is the smallest one in the stack Then, 3 |
| 24 | + // becomes the left child and 1*2 = 2 becomes right child. See below: |
| 25 | + // ... |
| 26 | + // / \ |
| 27 | + // 3 2 |
| 28 | + // / \ |
| 29 | + // 2 1 |
| 30 | + // |
| 31 | + |
| 32 | + // If we observe carefully, 3 2 1 is decreasing... So how about every time we see a "dip" point |
| 33 | + // in the array we calculate its multiplication. To do that, say we are at arr[i] and their |
| 34 | + // relations are arr[i-1] <= arr[i] <= arr[i+1]. The min multiplication is a[i] * min(arr[i-1], |
| 35 | + // arr[i+1]). Then the example above is arr[i] = 1, arr[i-1] = 2, arr[i+1] = 5 |
| 36 | + |
| 37 | + public int mctFromLeafValues(int[] arr) { |
| 38 | + if(arr == null || arr.length < 2){ |
| 39 | + return 0; |
| 40 | + } |
| 41 | + |
| 42 | + int res = 0; |
| 43 | + Stack<Integer> stack = new Stack<>(); |
| 44 | + for(int num : arr){ |
| 45 | + |
| 46 | + // while num is bigger than peek(), pop and calculate |
| 47 | + while(!stack.isEmpty() && stack.peek() <= num){ |
| 48 | + int mid = stack.pop(); |
| 49 | + if(stack.isEmpty()) |
| 50 | + res += mid * num; |
| 51 | + else |
| 52 | + res += mid * Math.min(stack.peek(), num); |
| 53 | + } |
| 54 | + |
| 55 | + stack.push(num); // if num is smaller, push into stack |
| 56 | + } |
| 57 | + |
| 58 | + // if there are values left in the stack, they sure will be mutiplied anyway |
| 59 | + // and added to the result. |
| 60 | + while(stack.size() > 1){ // > 1 because we have a peek() after pop() below |
| 61 | + res += stack.pop() * stack.peek(); |
| 62 | + } |
| 63 | + |
| 64 | + return res; |
27 | 65 | }
|
28 | 66 | }
|
0 commit comments