美文网首页算法
1130. 叶值的最小代价生成树

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

作者: 红树_ | 来源:发表于2023-05-30 17:47 被阅读0次

LC每日一题,参考1130. 叶值的最小代价生成树

题目

给你一个正整数数组 arr,考虑所有满足以下条件的二叉树:

  • 每个节点都有 0 个或是 2 个子节点。
  • 数组 arr 中的值与树的中序遍历中每个叶节点的值一一对应。
  • 每个非叶节点的值等于其左子树和右子树中叶节点的最大值的乘积(叶节点的子节点数为0)。

在所有这样的二叉树中,返回每个非叶节点的值的最小可能总和。这个和的值是一个 32 位整数。

输入:arr = [6,2,4]
输出:32
解释:有两种可能的树,第一种的非叶节点的总和为 36 ,第二种非叶节点的总和为 32 。 

解题思路

  • 递归+记忆化搜索:考虑递归实现,用记忆化搜索优化。

递归+记忆化搜索

class Solution {
    public int mctFromLeafValues(int[] arr) {
        int n = arr.length;
        int[][] max = new int[n][n]; // 定义一个二维数组来记录区间最大值
        for (int i = 0; i < n; i++) {
            int curMax = 0;
            for (int j = i; j < n; j++) {
                curMax = Math.max(curMax, arr[j]); // 求出[i,j]的最大值
                max[i][j] = curMax; // 记录[i,j]区间最大值
            }
        }
        return dfs(arr, 0, n - 1, max, new int[n][n]); // 从根节点开始递归
    }

    private int dfs(int[] arr, int start, int end, int[][] max, int[][] memo) {
        if (start == end) return 0; // 叶子节点,返回0
        if (memo[start][end] > 0) return memo[start][end]; // 如果当前结点已经被访问过,直接返回结果
        int res = Integer.MAX_VALUE;
        // 枚举分割点i
        for (int i = start; i < end; i++) {
            res = Math.min(res, dfs(arr, start, i, max, memo)
                + dfs(arr, i + 1, end, max, memo)
                + max[start][i] * max[i + 1][end]); // 左右子树+加上当前结点
        }
        return memo[start][end] = res; // 记录当前结点的计算结果
    }
}

复杂度分析

  • 时间复杂度:O(n^3),最大值前缀和为n^2,记忆化搜索状态个数n^2,单个状态计算时间n,总时间复杂度为T(n^2 + n^3) = O(n^3)
  • 空间复杂度:O(n^2),前缀和和记忆化数组空间n^2

相关文章

网友评论

    本文标题:1130. 叶值的最小代价生成树

    本文链接:https://www.haomeiwen.com/subject/ynleedtx.html