Minimum Cost Tree From Leaf Values

medium monotonic stack greedy array

Problem

Given an array arr of positive integers, build a binary tree whose leaves are the array values in order (left to right). Each internal node's value is the product of the largest leaf in its left subtree and the largest leaf in its right subtree. Return the smallest possible sum of all internal node values.

Key idea: each value will eventually be "merged away" by pairing it with a neighbour; the merge cost is removed × larger-neighbour. To minimise total cost, greedily remove the smallest leaf first, pairing it with the smaller of its two neighbours. A monotonic (decreasing) stack does this in one pass.

Inputarr = [6, 2, 4]
Output32
Remove 2 (smallest), pairing with min(6, 4) = 4 → cost 2×4 = 8. Now [6, 4]: remove 4, pair with 6 → cost 4×6 = 24. Total 8 + 24 = 32.

def mctFromLeafValues(arr):
    total = 0
    stack = [float('inf')]
    for x in arr:
        while stack[-1] <= x:
            mid = stack.pop()
            total += mid * min(stack[-1], x)
        stack.append(x)
    while len(stack) > 2:
        total += stack.pop() * stack[-1]
    return total
function mctFromLeafValues(arr) {
  let total = 0;
  const stack = [Infinity];
  for (const x of arr) {
    while (stack[stack.length - 1] <= x) {
      const mid = stack.pop();
      total += mid * Math.min(stack[stack.length - 1], x);
    }
    stack.push(x);
  }
  while (stack.length > 2) {
    total += stack.pop() * stack[stack.length - 1];
  }
  return total;
}
class Solution {
    public int mctFromLeafValues(int[] arr) {
        int total = 0;
        Deque<Integer> stack = new ArrayDeque<>();
        stack.push(Integer.MAX_VALUE);
        for (int x : arr) {
            while (stack.peek() <= x) {
                int mid = stack.pop();
                total += mid * Math.min(stack.peek(), x);
            }
            stack.push(x);
        }
        while (stack.size() > 2) {
            total += stack.pop() * stack.peek();
        }
        return total;
    }
}
int mctFromLeafValues(vector<int>& arr) {
    int total = 0;
    vector<int> stack = { INT_MAX };
    for (int x : arr) {
        while (stack.back() <= x) {
            int mid = stack.back(); stack.pop_back();
            total += mid * min(stack.back(), x);
        }
        stack.push_back(x);
    }
    while ((int)stack.size() > 2) {
        int mid = stack.back(); stack.pop_back();
        total += mid * stack.back();
    }
    return total;
}
Time: O(n) Space: O(n)