2021-02-26:一个数组arr是二叉树的中序遍历结果,每条边的开销是父节点和子节点的乘积,总开
2021-02-26 22:21
771 查看
2021-02-26:一个数组arr是二叉树的中序遍历结果,每条边的开销是父节点和子节点的乘积,总开销是所有边的开销之和。请问最小总开销是多少?
链接:https://www.nowcoder.com/questionTerminal/0d939e874a004f449a370aca1346dd5c
来源:牛客网
小团有一个由N个节点组成的二叉树,每个节点有一个权值。定义二叉树每条边的开销为其两端节点权值的乘积,二叉树的总开销即每条边的开销之和。小团按照二叉树的中序遍历依次记录下每个节点的权值,即他记录下了N个数,第i个数表示位于中序遍历第i个位置的节点的权值。之后由于某种原因,小团遗忘了二叉树的具体结构。在所有可能的二叉树中,总开销最小的二叉树被称为最优二叉树。现在,小团请小美求出最优二叉树的总开销。
输入描述:
第一行输入一个整数N(1<=N<=300),表示二叉树的节点数。
第二行输入N个由空格隔开的整数,表示按中序遍历记录下的各个节点的权值,所有权值均为不超过1000的正整数。
输出描述:
输出一个整数,表示最优二叉树的总开销。
福哥答案2021-02-26:
自然智慧即可。
1.递归。有代码。
2.记忆化搜索。有代码。
代码用golang编写,代码如下:
package main import "fmt" const MAX = int(^uint(0) >> 1) //https://www.nowcoder.com/questionTerminal/0d939e874a004f449a370aca1346dd5c func main() { arr := []int{7, 6, 5, 1, 3} ret := f1(arr) fmt.Println("1.递归:", ret) ret = f2(arr) fmt.Println("2.记忆化搜索:", ret) } func f1(arr []int) int { arrLen := len(arr) if arrLen <= 1 { return 0 } return process1(arr, -1, 0, arrLen-1) } func process1(arr []int, cur int, L int, R int) int { length := R - L + 1 if length == 0 { return 0 } ans := MAX for i := L; i <= R; i++ { temp := 0 if cur >= 0 { temp = arr[cur] * arr[i] } ans = getMin(temp+process1(arr, i, L, i-1)+process1(arr, i, i+1, R), ans) } return ans } func f2(arr []int) int { arrLen := len(arr) if arrLen <= 1 { return 0 } dp := make([][][]int, arrLen+1) for i := 0; i < arrLen+1; i++ { dp[i] = make([][]int, arrLen) for j := 0; j < arrLen; j++ { dp[i][j] = make([]int, arrLen) for k := 0; k < arrLen; k++ { dp[i][j][k] = -1 } } } ret := process2(arr, -1, 0, arrLen-1, dp) //fmt.Println(dp) return ret } func process2(arr []int, cur int, L int, R int, dp [][][]int) int { length := R - L + 1 if length == 0 { return 0 } if dp[cur+1][L][R] != -1 { //fmt.Println("记忆化", dp[cur+1][L][R]) return dp[cur+1][L][R] } ans := MAX for i := L; i <= R; i++ { temp := 0 if cur >= 0 { temp = arr[cur] * arr[i] } ans = getMin(temp+process2(arr, i, L, i-1, dp)+process2(arr, i, i+1, R, dp), ans) } dp[cur+1][L][R] = ans return ans } func getMin(a int, b int) int { if a < b { return a } else { return b } }
执行结果如下:
相关文章推荐
- 【二叉树】寻找一个二叉树的节点在中序遍历中的后继节点
- 51. 腾讯面试题:一个二叉树,中序遍历,找一个节点的后一个节点
- 实现函数 makeClosures,调用之后满足如下条件: 1、返回一个函数数组 result,长度与 arr 相同 2、运行 result 中第 i 个函数,即 result[i](),结果与 fn
- 给定一个二叉树和其中的一个节点,求中序遍历这个节点的下一个节点
- 二叉树的实现&&递归和非递归方式前序、中序、后续遍历&&发现一个节点中序遍历的下一节点
- 求二叉树叶子节点的个数/求二叉树第k层的节点个数/一个数组中有一个数字的次数超过了数组的一半,求出这个字符
- 51. 腾讯面试题:一个二叉树,中序遍历,找一个节点的后一个节点
- 已知一颗二叉树,如果先序遍历的节点顺序是:ADCEFGHB,中序遍历是,CDFEGHAB,则后序遍历的结果为
- 输入一个数组,判断该数组是否是某二叉树的前序遍历结果
- 一个关于二叉树的创建、先序遍历、中序遍历、后序遍历、求叶子节点的完整函数的c语言完整程序。
- 从上往下打印二叉树,判断该数组是不是某二叉搜索树的后序,前序,或者是中序遍历的结果,二叉树中和为某一值的路径
- 二叉树 给定一个节点,求中序遍历下一个节点
- 数据结构:题目(3)测试一个数组序列是否是二叉树的前序遍历或者后序遍历结果
- 判断一个数组是不是二叉树后序遍历的结果
- 试编写一个函数,返回一颗给定二叉树在中序遍历下的最后一个节点(分别用递归和非递归实现)
- 数据结构 前序遍历结果 中序遍历结果确定二叉树
- 给定一个递增排序的数组和一个数字s,求数组中和为s的俩个数。求乘积最小的俩个数
- 二叉树相关操作(先序建立二叉树、求子节点数量,判断是否为平衡二叉树,先序遍历,中序遍历,后序遍历)
- Cracking coding interview(4.3)给定一个排好序的数组创建最小高度的二叉树
- 判断一个节点是否在一棵二叉树中和判断一颗二叉树是否是另一颗树的子树——题集(十二)