实例:
先序遍历为:1 2 4 5 3 6,中序遍历为:4 2 5 1 6 3
思路:
先序遍历的第一个元素为根节点,在中序遍历中找到这个根节点,从而可以将中序遍历分为左右两个部分,左边部分为左子树的中序遍历,右边部分为右子树的中序遍历,进而也可以将先序遍历除第一个元素以外的剩余部分分为两个部分,第一个部分为左子树的先序遍历,第二个部分为右子树的先序遍历。
由上述分析结果,可以递归调用构建函数,根据左子树、右子树的先序、中序遍历重建左、右子树。
代码:
public class Solution7
{
public class TreeNode
{
int val;
TreeNode left;
TreeNode right;
TreeNode(int x)
{
val = x;
}
}
public TreeNode reConstructBinaryTree(int [] pre,int [] in)
{
if(pre.length==0 || in.length==0)
return null;
//先序遍历与中序遍历长度不同返回null
if(pre.length!=in.length)
return null;
TreeNode root=new TreeNode(pre[0]);
root.left=null;
root.right=null;
//只有一个节点时,返回根节点
if(pre.length==1 && in.length==1)
return root;
int index=-1;//记录根节点的位置
//查找中序序列中根节点的位置
for(int i=0;i<in.length;i++)
{
if(in[i]==pre[0])
{
index=i;
break;
}
}
if(index==-1)//中序中无根节点
return null;
if(index-0>0) //有左子树
{
int[] preLeftTree=new int[index];//记录左子树的先序遍历序列
for(int i=0;i<index;i++)
{
preLeftTree[i]=pre[i+1];
}
int[] inLeftTree=new int[index];//记录左子树的中序遍历序列
for(int i=0;i<index;i++)
{
inLeftTree[i]=in[i];
}
root.left=reConstructBinaryTree(preLeftTree,inLeftTree);
}
if(in.length-1-index>0)//有右子树
{
int[] preRightTree=new int[in.length-1-index];//(in.length-1-index)右子树的元素个数
int m=0;
for(int i=index+1;i<pre.length;i++)//记录右子树的先序遍历序列
{
preRightTree[m]=pre[i];
m++;
}
int[] inRightTree=new int[in.length-1-index];
int j=0;
for(int i=index+1;i<in.length;i++)记录右子树的中序遍历序列
{
inRightTree[j]=in[i];
j++;
}
root.right=reConstructBinaryTree(preRightTree,inRightTree);
}
return root;
}
//后序遍历
public void post(TreeNode root)
{
if(root.left!=null)
post(root.left);
if(root.right!=null)
post(root.right);
System.out.print(root.val+" ");
}
public static void main(String[] args)
{
int[] pre= {1,2,4,5,3,6};
int[] in= {4,2,5,1,6,3};
Solution7 s7=new Solution7();
TreeNode root=s7.reConstructBinaryTree(pre, in);
s7.post(root);
}
}
输出:
4 5 2 6 3 1