题目:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
eg: 输入:[1,2,3,4,5,6,7],[3,2,4,1,6,5,7]
输出:{1,2,5,3,4,6,7}
真不敢相信我写出来了。。。二叉树重建在之前数据结构的课上就学过,通过先序遍历和中序遍历能够确定一棵二叉树,思路其实还挺简单的,根据先序遍历可以确定根节点,结合中序遍历确定左右子树,递归地进行判断。
以例题为例,对于先序遍历 1,2,3,4,5,6,7,可以确定根节点是1,在中序遍历中找到1,那么1的左边就是其左子树3,2,4,右边就是右子树6,5,7,然后根据左子树的长度3,可以在先序遍历中确定子树的先序遍历,从根节点的后面3个构成了左子树的先序2,3,4,后面的元素则是右子树的先序,5,6,7,并且对于先序遍历,第一个元素是根节点,因此可以直接确定1的左孩子是2,右孩子是5,构建出其父子关系,然后分别以左孩子为根节点,对左子树递归进行重建,以右孩子为根节点,对右孩子进行构建,直到每个区间只有一个节点,则直接返回,因为对于单个节点,已经在上一步进行处理了。
完整代码如下:
public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
if(pre.length==0) {
return null;
}
TreeNode root = new TreeNode(pre[0]);
reConstruct(root, pre, in, 0, pre.length-1, 0, in.length-1);
return root;
}
public static void reConstruct(TreeNode root,int[] pre,int[]in,int pb,int pe,int ib,int ie) {
if(pb>=pe) {
return ;
}
int r = pre[pb];
int index = find(in, r); //index为root节点在中序遍历中位置,根据index划分左右子树
//中序左子树 [ib,index-1] 右子树[index+1,ie]
int len = index-ib; //左子树长度
//先序左子树 [pb+1,pb+len] 右子树[pb+len+1,pe]
if(pb+1<=pb+len) {//如果左孩子存在
TreeNode lchild = new TreeNode(pre[pb+1]);
root.left = lchild;
}
if(pb+len+1<=pe) { //如果右孩子存在
TreeNode rchild = new TreeNode(pre[pb+len+1]);
root.right = rchild;
}
reConstruct(root.left, pre, in, pb+1, pb+len, ib, index-1);
reConstruct(root.right, pre, in, pb+len+1, pe, index+1, ie);
}
public static int find(int[] arr,int index) {
for(int i=0;i<arr.length;i++) {
if(arr[i]==index) {
return i;
}
}
return -1;
}