LeetCode 题解工作台

叶值的最小代价生成树

给你一个正整数数组 arr ,考虑所有满足以下条件的二叉树: 每个节点都有 0 个或是 2 个子节点。 数组 arr 中的值与树的中序遍历中每个叶节点的值一一对应。 每个非叶节点的值等于其左子树和右子树中叶节点的最大值的乘积。 在所有这样的二叉树中,返回每个非叶节点的值的最小可能总和。这个和的值是一…

category

5

题型

code_blocks

5

代码语言

hub

3

相关题

当前训练重点

中等 · 状态·转移·动态规划

bolt

答案摘要

根据题目描述,数组 中的值与树的中序遍历中每个叶节点的值一一对应,我们可以将数组划分为左右两个非空子数组,分别对应树的左右子树,递归地求解每个子树的所有非叶节点的值的最小可能总和。 我们设计一个函数 $dfs(i, j)$,表示数组 中下标范围 $[i, j]$ 内的所有非叶节点的值的最小可能总和,那么答案就是 $dfs(0, n - 1)$,其中 为数组 的长度。

Interview AiBox logo

Interview AiBox 实时 AI 助手,陪你讲清 状态·转移·动态规划 题型思路

试试 AiBox 面试助手arrow_forward
description

题目描述

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

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

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

如果一个节点有 0 个子节点,那么该节点为叶节点。

 

示例 1:

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

示例 2:

输入:arr = [4,11]
输出:44

 

提示:

  • 2 <= arr.length <= 40
  • 1 <= arr[i] <= 15
  • 答案保证是一个 32 位带符号整数,即小于 231
lightbulb

解题思路

方法一:记忆化搜索

根据题目描述,数组 arrarr 中的值与树的中序遍历中每个叶节点的值一一对应,我们可以将数组划分为左右两个非空子数组,分别对应树的左右子树,递归地求解每个子树的所有非叶节点的值的最小可能总和。

我们设计一个函数 dfs(i,j)dfs(i, j),表示数组 arrarr 中下标范围 [i,j][i, j] 内的所有非叶节点的值的最小可能总和,那么答案就是 dfs(0,n1)dfs(0, n - 1),其中 nn 为数组 arrarr 的长度。

函数 dfs(i,j)dfs(i, j) 的计算过程如下:

  • 如果 i=ji = j,说明数组 arr[i..j]arr[i..j] 中只有一个元素,没有非叶节点,因此 dfs(i,j)=0dfs(i, j) = 0
  • 否则,我们枚举 k[i,j1]k \in [i, j - 1],将数组 arrarr 划分为两个子数组 arr[ik]arr[i \cdots k]arr[k+1j]arr[k + 1 \cdots j],对于每个 kk,我们递归计算 dfs(i,k)dfs(i, k)dfs(k+1,j)dfs(k + 1, j),其中 dfs(i,k)dfs(i, k) 表示数组 arrarr 中下标范围 [i,k][i, k] 内的所有非叶节点的值的最小可能总和,而 dfs(k+1,j)dfs(k + 1, j) 表示数组 arrarr 中下标范围 [k+1,j][k + 1, j] 内的所有非叶节点的值的最小可能总和,那么 dfs(i,j)=minik<j{dfs(i,k)+dfs(k+1,j)+maxitk{arr[t]}maxk<tj{arr[t]}}dfs(i, j) = \min_{i \leq k < j} \{dfs(i, k) + dfs(k + 1, j) + \max_{i \leq t \leq k} \{arr[t]\} \max_{k < t \leq j} \{arr[t]\}\}

综上所述,我们可以得到:

dfs(i,j)={0,if i=jminik<j{dfs(i,k)+dfs(k+1,j)+maxitk{arr[t]}maxk<tj{arr[t]}},if i<jdfs(i, j) = \begin{cases} 0, & \textit{if } i = j \\ \min_{i \leq k < j} \{dfs(i, k) + dfs(k + 1, j) + \max_{i \leq t \leq k} \{arr[t]\} \max_{k < t \leq j} \{arr[t]\}\}, & \textit{if } i < j \end{cases}

上述递归过程中,我们可以使用记忆化搜索的方法,避免重复计算。另外,我们还可以使用数组 gg 记录数组 arrarr 中下标范围 [i,j][i, j] 内的所有叶节点的最大值,那么 dfs(i,j)dfs(i, j) 的计算过程可以优化为:

dfs(i,j)={0,if i=jminik<j{dfs(i,k)+dfs(k+1,j)+g[i][k]g[k+1][j]},if i<jdfs(i, j) = \begin{cases} 0, & \textit{if } i = j \\ \min_{i \leq k < j} \{dfs(i, k) + dfs(k + 1, j) + g[i][k] \cdot g[k + 1][j]\}, & \textit{if } i < j \end{cases}

最后,我们返回 dfs(0,n1)dfs(0, n - 1) 即可。

时间复杂度 O(n3)O(n^3),空间复杂度 O(n2)O(n^2)。其中 nn 为数组 arrarr 的长度。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Solution:
    def mctFromLeafValues(self, arr: List[int]) -> int:
        @cache
        def dfs(i: int, j: int) -> Tuple:
            if i == j:
                return 0, arr[i]
            s, mx = inf, -1
            for k in range(i, j):
                s1, mx1 = dfs(i, k)
                s2, mx2 = dfs(k + 1, j)
                t = s1 + s2 + mx1 * mx2
                if s > t:
                    s = t
                    mx = max(mx1, mx2)
            return s, mx

        return dfs(0, len(arr) - 1)[0]
speed

复杂度分析

指标
时间Depends on the final approach
空间Depends on the final approach
psychology

面试官常问的追问

外企场景
  • question_mark

    Do you consider overlapping subproblems for the subarray DP?

  • question_mark

    Can you reduce the O(n^3) DP with a greedy or stack-based method?

  • question_mark

    How do you maintain maximum leaf values efficiently during subarray merges?

warning

常见陷阱

外企场景
  • error

    Forgetting to correctly compute max(arr[i..k]) and max(arr[k+1..j]) in DP can inflate the sum.

  • error

    Incorrect stack handling can merge the wrong neighbors, giving a larger non-leaf sum.

  • error

    Not memoizing subarray results leads to TLE on larger arrays up to 40 elements.

swap_horiz

进阶变体

外企场景
  • arrow_right_alt

    Minimizing non-leaf sum when node value is the sum of maximum leaves instead of product.

  • arrow_right_alt

    Finding maximum non-leaf sum instead of minimum for the same leaf array.

  • arrow_right_alt

    Allowing leaves to appear multiple times, requiring adjusted DP state.

help

常见问题

外企场景

叶值的最小代价生成树题解:状态·转移·动态规划 | LeetCode #1130 中等