重建二叉树

题目描述

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

解题思路

  • root最简单,前序遍历序列{1,2,4,7,3,5,6,8}的第一节点1就是root。
  • 中序遍历序列{4,7,2,1,5,3,8,6} 其中root节点1左侧的4,7,2必然是root的左子树,1右侧的5,3,8,6必然是root的右子树。
  • 观察左子树4,7,2,左子树的中的根节点必然是大树的root的leftchild。在前序遍历中,大树的root的leftchild位于root之后,所以左子树的根节点为2。
  • 同样的道理,root的右子树节点5,3,8,6中的根节点也可以通过前序遍历求得。在前序遍历中,一定是先把root和root的所有左子树节点遍历完之后才会遍历右子树,并且遍历的右子树的第一个节点就是右子树的根节点。
  • 中序遍历中,root左侧是4,7,2,所以有3个节点位于root左侧。那么在前序遍历中,必然是第1个是1,第2到第4个由4,7,2组成,第5个就是root的右子树的根节点了,是3。
  • 观察发现,上面的过程是递归的。先找到当前树的根节点,然后划分为左子树,右子树,然后进入左子树重复上面的过程,然后进入右子树重复上面的过程。最后就可以还原一棵树了。

代码

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
/**
* Definition for binary tree
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
import java.util.HashMap;
import java.util.Map;
public class Solution {
private Map<Integer, Integer> indexForInOrders = new HashMap<>();
public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
for (int i = 0; i < in.length; i++) {
// 缓存中序遍历数组每个值对应的索引
indexForInOrders.put(in[i], i);
}
return reBuild(pre, 0, pre.length - 1, 0);
}
//rootNodeIndex为根节点的索引,endNodeIndex为前序遍历序列的最后一个节点索引,leftNodeIndex为二叉树的中序遍历的第一个节点索引
private TreeNode reBuild(int[] pre, int rootNodeIndex, int endNodeIndex, int leftNodeIndex) {
if (rootNodeIndex > endNodeIndex) {
return null;
}
//确立根结点
TreeNode root = new TreeNode(pre[rootNodeIndex]);
//找到根节点所在索引位置,并分出左子树,右子树。
int inIndex = indexForInOrders.get(root.val);
int leftTreeSize = inIndex - leftNodeIndex;
//递归将左子树,右子树重复之前的过程。
root.left = reBuild(pre, rootNodeIndex + 1, rootNodeIndex + leftTreeSize, leftNodeIndex);
root.right = reBuild(pre, rootNodeIndex + leftTreeSize + 1, endNodeIndex, leftNodeIndex + leftTreeSize + 1);
return root;
}
}
坚持原创技术分享,您的支持将鼓励我继续创作!