给你一个正整数数组 arr,考虑所有满足以下条件的二叉树:
每个节点都有 0 个或是 2 个子节点。
数组 arr 中的值与树的中序遍历中每个叶节点的值一一对应。
每个非叶节点的值等于其左子树和右子树中叶节点的最大值的乘积。
在所有这样的二叉树中,返回每个非叶节点的值的最小可能总和。这个和的值是一个 32 位整数。
如果一个节点有 0 个子节点,那么该节点为叶节点。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/minimum-cost-tree-from-leaf-values
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
动态规划
import java.util.Arrays;
class Solution {
public int mctFromLeafValues(int[] arr) {
if (arr == null || arr.length < 2) {
return 0;
}
int n = arr.length;
int[][] dp = new int[n][n];
int[][] mal = new int[n][n];
for (int i = 0; i < n; i++) {
mal[i][i] = arr[i];
for (int j = i + 1; j < n; j++) {
mal[i][j] = Math.max(mal[i][j - 1], arr[j]);
}
}
int INF = Integer.MAX_VALUE;
for (int i = n - 1; i >= 0; i--) {
for (int j = i + 1; j < n; j++) {
dp[i][j] = INF;
for (int k = i; k < j; k++) {
dp[i][j] = Math.min(dp[i][j], dp[i][k] + dp[k + 1][j] + mal[i][k] * mal[k + 1][j]);
}
}
}
return dp[0][n - 1];
}
}
单调栈
import java.util.Arrays;
import java.util.Stack;
class Solution {
public int mctFromLeafValues(int[] arr) {
if (arr == null || arr.length < 2) {
return 0;
}
Stack<Integer> stack = new Stack<>();
int ans = 0;
for (int x : arr) {
while (!stack.isEmpty() && stack.peek() <= x) {
Integer pop = stack.pop();
if (stack.isEmpty() || stack.peek() >= x) {
ans += x * pop;
} else {
ans += stack.peek() * pop;
}
}
stack.push(x);
}
while (stack.size() >= 2) {
ans += stack.pop() * stack.peek();
}
return ans;
}
}