1130. 叶值的最小代价生成树

发布时间 2023-06-01 10:56:15作者: Tianyiya

给你一个正整数数组 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;
    }
}