给你一个正整数数组 arr,考虑所有满足以下条件的二叉树:
每个节点都有 0 个或是 2 个子节点。
数组 arr 中的值与树的中序遍历中每个叶节点的值一一对应。(知识回顾:如果一个节点有 0 个子节点,那么该节点为叶节点。)
每个非叶节点的值等于其左子树和右子树中叶节点的最大值的乘积。
在所有这样的二叉树中,返回每个非叶节点的值的最小可能总和。这个和的值是一个 32 位整数。
示例:
输入:arr = [6,2,4]
输出:32
解释:
有两种可能的树,第一种的非叶节点的总和为 36,第二种非叶节点的总和为 32。
24 24
/ \ / \
12 4 6 8
/ \ / \
6 2 2 4
提示:
2 <= arr.length <= 40
1 <= arr[i] <= 15
答案保证是一个 32 位带符号整数,即小于 2^31。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/minimum-cost-tree-from-leaf-values
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
最大的最小值(最小的最大值)问题
先求max矩阵:表示arr数组,i到j内的最大值
dp[i][j]表示i到j区间内的非叶子结点的最小总和
对于i、j 相邻j = i + 1,显然dp[i][j] = arr[i] * arr[j](需要预处理)
对于相邻三个节点 例如dp[0][3]
下标: 0 1. 2
假如三个数分别是 1, 2, 3
那么可以组合的情况是 (1, 2), 3 | 1,(2, 3)
那么dp[0][3] = min(dp[0][1] + arr[2] * max[0][1], arr[0] * max[1][2] + dp[1][2])
对于更多的节点
作者:zwhyS7
链接:https://leetcode.cn/problems/minimum-cost-tree-from-leaf-values/solution/golang-by-zwhys7-p5fd/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
下标:0, 1, 2, 3, 4
例如五个节点 1, 2, 3, 4, 5
先处理边界分类的情况:1 (2, 3, 4, 5); (1, 2, 3, 4), 5
这样可以避免 从i 到j 之间劈开进行讨论的时候,如果出现dp[0][3] 和dp[4][4]的情况,避免k = j - 1
对于其他分类情况,比如 (1, 2, 3) (4, 5) // i = 0, j = 4, k 属于i + 1 -> j - 2
dp[0][4] = min(dp[0][4], dp[0][2] /*左侧非页节点之和 */ + dp[3][4] /*右侧非叶子之和*/ + max[0][2] * max[3][4] /*跟节点的值*/)
作者:zwhyS7
链接:https://leetcode.cn/problems/minimum-cost-tree-from-leaf-values/solution/golang-by-zwhys7-p5fd/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
func mctFromLeafValues(arr []int) int {
n := len(arr)
dp, max := make([][]int, n), make([][]int, n)
for i := 0; i < n; i++{
dp[i] = make([]int, n)
max[i] = make([]int, n)
max[i][i] = arr[i]
}
for i := 0; i < n; i++{
cur := arr[i]
for j := i + 1; j < n; j++{
if arr[j] > cur{
cur = arr[j]
}
max[i][j] = cur
}
}
for i := 1; i < n; i++{
dp[i - 1][i] = arr[i - 1] * arr[i]
}
for i := n - 3; i >= 0; i--{ // 单个节点n - 1没意义跳过,n - 2 到 n - 1属于相邻的两个节点,已经预处理了
for j := i + 2; j < n; j++{ // j从i + 2开始,因为i + 1属于相邻的节点 预处理了已经
// 这里,见 5
dp[i][j] = min(arr[i] * max[i + 1][j] + dp[i + 1][j], dp[i][j - 1] + max[i][j - 1] * arr[j])
if j == i + 2{ // 三个相邻的话,上一行代码就已经处理完了,不需要走下面
continue
}
// k
for k := i + 1; k < j - 1; k++{
dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j] + max[i][k] * max[k + 1][j])
}
}
}
return dp[0][n - 1]
}
func min(x, y int)int{
if x <= y{
return x
}
return y
}
作者:zwhyS7
链接:https://leetcode.cn/problems/minimum-cost-tree-from-leaf-values/solution/golang-by-zwhys7-p5fd/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。