105. 从前序与中序遍历序列构造二叉树
题目描述:
给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。
示例 1:
输入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
输出: [3,9,20,null,null,15,7]
示例 2:
输入: preorder = [-1], inorder = [-1]
输出: [-1]
提示:
- 1 <= preorder.length <= 3000
- inorder.length == preorder.length
- -3000 <= preorder[i], inorder[i] <= 3000
- preorder 和 inorder 均 无重复 元素
- inorder 均出现在 preorder
- preorder 保证 为二叉树的前序遍历序列
- inorder 保证 为二叉树的中序遍历序列
解题分析及思路:
这道题考察的是二叉树的遍历,不熟悉二叉树的遍历可以查看二叉树。
题目给出的是前序遍历和中序遍历后的结果,由此重新生成原有的二叉树。
将一棵二叉树分别进行前序遍历和后序遍历:
- 针对前序遍历后的结果,可以分析出结果的构成为
[ 根节点, [左子树的前序遍历结果], [右子树的前序遍历结果] ]
- 针对中序遍历后的结果,可以分析出结果的构成为
[ [左子树的中序遍历结果], 根节点, [右子树的中序遍历结果] ]
而我们仅仅只需要根据前序遍历的第一个值,也就是根节点的值,即可定位到中序遍历根节点的位置。
随后根据中序遍历根节点的位置,可以将所有的数据划分为根节点的左右子树。
最后采取同样的方式(递归解决)分别定位左右子树的值及其子树。
其中,定位到根节点在中序遍历的下标为index
:
- 左子树的的前序遍历集合为
preorder[1:len(inorder[:index])+1]
,左子树的中序遍历集合为inorder[:index]
- 右子树的的前序遍历集合为
preorder[len(inorder[:index])+1:]
,右子树的中序遍历集合为inorder[index+1:]
func buildTree(preorder []int, inorder []int) *TreeNode {
if len(preorder) == 0 {
return nil
}
num := preorder[0]
index := 0
for i := range inorder {
if inorder[i] == num {
index = i
break
}
}
root := &TreeNode{Val: num}
root.Left = buildTree(preorder[1:len(inorder[:index])+1], inorder[:index])
root.Right = buildTree(preorder[len(inorder[:index])+1:], inorder[index+1:])
return root
}
复杂度:
- 时间复杂度:O(N),其中 N 是树中的节点个数.
- 空间复杂度:O(1),只使用常数额外空间。
执行结果:
- 执行耗时:3 ms,击败了86.55% 的Go用户
- 内存消耗:4 MB,击败了39.64% 的Go用户