题目描述
给定两个整数数组 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 保证 为二叉树的中序遍历序列
代码及注释
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func buildTree(preorder []int, inorder []int) *TreeNode {
// 使用一个哈希表存储中序遍历的值和其对应的索引
hash := map[int]int{}
// 如果前序遍历或中序遍历的长度为0,则返回nil
if len(preorder) < 1 || len(inorder) < 1 {
return nil
}
// 构建哈希表
for i := 0; i < len(inorder); i++ {
hash[inorder[i]] = i
}
// 前序遍历的第一个元素是当前子树的根节点
mid := preorder[0]
// 递归构建左右子树
root := &TreeNode{
Val: mid,
Left: buildTree(preorder[1:hash[mid] + 1], inorder[:hash[mid]]),
Right: buildTree(preorder[hash[mid] + 1:], inorder[hash[mid] + 1:]),
}
return root
}
代码解释
-
哈希表
hash
用于存储中序遍历的值和其对应的索引,这样在递归构建二叉树时可以快速找到根节点在中序遍历中的位置。 -
如果前序遍历
preorder
或中序遍历inorder
的长度为0,则表示当前的子树为空,直接返回nil
。 -
选择前序遍历的第一个元素作为当前子树的根节点
mid
。 -
在中序遍历
inorder
中找到mid
的索引hash[mid]
,这个索引将中序遍历分为左子树和右子树。 -
递归地构建左右子树,左子树的前序遍历是
preorder[1:hash[mid]+1]
,中序遍历是inorder[:hash[mid]]
;右子树的前序遍历是preorder[hash[mid]+1:]
,中序遍历是inorder[hash[mid]+1:]
。
示例
考虑以下前序遍历和中序遍历序列:
preorder = [3,9,20,15,7]
inorder = [9,3,15,20,7]
首先构建哈希表:
hash = {
9: 0,
3: 1,
15: 2,
20: 3,
7: 4,
}
根据前序遍历和中序遍历序列构建二叉树:
-
根节点是3,其左子树的前序遍历是[9],中序遍历是[9],右子树的前序遍历是[20,15,7],中序遍历是[15,20,7]。
-
继续递归构建左右子树。
最后得到二叉树如下:
3
/ \
9 20
/ \
15 7