从前序和中序构造二叉树

从前序和中序构造二叉树

给定两个整数数组 preorderinorder ,其中 preorder二叉树的先序遍历inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。

示例 1:

1
2
输入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
输出: [3,9,20,null,null,15,7]

示例 2:

1
2
输入: preorder = [-1], inorder = [-1]
输出: [-1]

解法 递归

对于任意一颗树而言,前序遍历的形式总是

1
[ 根节点, [左子树的前序遍历结果], [右子树的前序遍历结果] ]

即根节点总是前序遍历中的第一个节点。而中序遍历的形式总是

1
[ [左子树的中序遍历结果], 根节点, [右子树的中序遍历结果] ]

只要我们在中序遍历中定位到根节点,那么我们就可以分别知道左子树和右子树中的节点数目。由于同一颗子树的前序遍历和中序遍历的长度显然是相同的,因此我们就可以对应到前序遍历的结果中,对上述形式中的所有左右括号进行定位。

这样以来,我们就知道了左子树的前序遍历和中序遍历结果,以及右子树的前序遍历和中序遍历结果,我们就可以递归地对构造出左子树和右子树,再将这两颗子树接到根节点的左右位置

105-1.png

image.png

代码为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
Map<Integer,Integer> map = new HashMap<>();
public TreeNode buildTree(int[] preorder, int[] inorder) {
for (int i = 0;i<inorder.length;i++){
map.put(inorder[i],i);
}
int n = preorder.length;
return myBuildTree(preorder,inorder,0,n-1,0,n-1);
}
public TreeNode myBuildTree(int[] preorder, int[] inorder,int prel,int prer,int inl,int inr){
if (prel>prer) return null;
//在中序遍历中定位根节点
int root_index = map.get(preorder[prel]);
// 先把根节点建立出来
TreeNode root = new TreeNode(preorder[prel]);
//得到左子树中的节点数目
int size_left = root_index-inl;

// 递归地构造左子树,并连接到根节点
// 先序遍历中「从 左边界+1 开始的 size_left_subtree」个元素就对应了中序遍历中「从 左边界 开始到 根节点定位-1」的元素
root.left = myBuildTree(preorder,inorder,prel+1,prel+size_left,inl,root_index-1);

// 递归地构造右子树,并连接到根节点
// 先序遍历中「从 左边界+1+左子树节点数目 开始到 右边界」的元素就对应了中序遍历中「从 根节点定位+1 到 右边界」的元素
root.right = myBuildTree(preorder,inorder,prel+size_left+1,prer,root_index+1,inr);
return root;
}
}

从前序和中序构造二叉树
http://example.com/2022/09/08/从前序和中序构造二叉树/
作者
zlw
发布于
2022年9月8日
许可协议