题目描述
某二叉树的先序遍历结果记录于整数数组 preorder
,它的中序遍历结果记录于整数数组 inorder
。请根据 preorder
和 inorder
的提示构造出这棵二叉树并返回其根节点。
注意:preorder
和 inorder
中均不含重复数字。
示例 1:
输入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7] 输出: [3,9,20,null,null,15,7]
正常解法
对于树的大部分问题我们都会考虑递归的方式,通过确定根节点然后递归左子树和右子树,就可以实现构建树
具体代码实现:
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func deduceTree(preorder []int, inorder []int) *TreeNode {
k := 0
n := len(preorder)
var dfs func(int, int)*TreeNode
dfs = func(l, r int) *TreeNode {
if l > r {
return nil
}
// 拿到根结点
x := preorder[k]
k++
mid := 0
// 拿到中序遍历中根结点位置
for i:=0; i <= r; i++ {
if x == inorder[i]{
mid = i
break
}
}
// 不断拿到不同子树的根节点
left := dfs(l, mid - 1)
right := dfs(mid + 1, r)
root := &TreeNode{Val: x}
root.Left = left
root.Right = right
return root
}
return dfs(0, n-1)
}
但是这种方法因为递归中我们使用循环去确定不同子树的根节点,会导致大量的遍历操作,所以运行时间会稍微差点
解法二
我们可以将中序遍历中,每个元素的位置用一个集合记录下来,然后可以直接在递归中取用,少了不断循环的遍历
具体代码:
func deduceTree(preorder []int, inorder []int) *TreeNode {
k := 0
n := len(preorder)
dic := map[int]int{}
for i, v := range inorder{
dic[v] = i
}
var dfs func(int, int)*TreeNode
// l 和 r 确定左子树和右子树的边界
dfs = func(l, r int) *TreeNode {
if l > r {
return nil
}
// 拿到根结点的值
x := preorder[k]
k++
//拿到中序遍历中根结点位置
mid := dic[x]
// 不断拿到不同子树的根节点
// 最终 mid - 1 会等于 -1,就结束递归
left := dfs(l, mid - 1)
right := dfs(mid + 1, r)
root := &TreeNode{Val: x}
root.Left = left
root.Right = right
return root
}
return dfs(0, n-1)
}