输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
思路:在二叉树的前序遍历序列中,第一个数字总是树的根节点的值。但在中序遍历中,根节点的值再序列的中间,左子树的节点的值位于根节点的值的左边而右子树的节点的值位于根节点的值的右边,这样就能够确定左、右子树节点的数量。在前序遍历和中序遍历的序列中划分了左、右子树节点的之后,就可以递归的调用函数reConstructTree,去分别构建它的左右子树。
package co.com.jianzhioffer;
import java.util.Scanner;
public class Solution4 {
/*
* 内部类:节点
*/
private static class TreeNode{
TreeNode leftChild;
TreeNode rightChild;
int data;
TreeNode(int newData){
leftChild = null;
rightChild = null;
data = newData;
}
}
//考虑比较全面,特殊的情况也考虑了
public static TreeNode reConstructBinaryTree(int[] pre,int[] in){
if(pre == null || in == null || pre.length!=in.length){
return null;
}
TreeNode root = reConstructBinaryTree(pre,0, pre.length-1,in,0,in.length-1);
return root;
}
/*
* 根据二叉树的谦虚遍历和中序遍历来重建二叉树
*/
public static TreeNode reConstructBinaryTree(int[] pre,int startPre,int endPre,int[] in,int startIn,int endIn){
if(startPre>endPre||startIn>endIn){
return null;
}
TreeNode root = new TreeNode(pre[startPre]);
/*
* 从中序遍历中找到根节点
*/
int i = 0;
for(i = startIn;i<=endIn;i++){
if(in[i] == pre[startPre]){
root.leftChild = reConstructBinaryTree(pre, startPre+1, startPre+i-startIn, in, startIn, i-1);
root.rightChild = reConstructBinaryTree(pre, startPre+i-startIn+1, endPre, in, i+1, endIn);
break;
}
}
//没有找到跟节点
if(i == endIn && in[i] != pre[startPre]){
return null;
}
return root;
}
/*
* 递归前序遍历,只是为了检验。
*/
public static void preOrderTraverse(TreeNode node){
if(node==null)
return;
System.out.print(node.data+" ");
preOrderTraverse(node.leftChild);
preOrderTraverse(node.rightChild);
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int m = sc.nextInt();
int[] pre = new int[m];
int[] in = new int[m];
TreeNode root = null;
for(int i = 0;i<m;i++){
pre[i] = sc.nextInt();
}
for(int i = 0;i<m;i++){
in[i] = sc.nextInt();
}
root = reConstructBinaryTree(pre, 0, pre.length-1, in, 0, in.length-1);
preOrderTraverse(root);;
}
}