题目描述
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
解题思路
方法:递归解决
思路:重建二叉树只能通过前序遍历和中序遍历或者中序遍历和后序遍历来实现,因为其原理就是递归实现通过前序遍历中的第一个节点(根节点,或者后序遍历中的最后一个节点)对中序遍历进行划分这一操作。
代码
/*
* 1.constructByPreMid() ==》 通过前序遍历和中序遍历,重建二叉树
* 2.constructByMidPos() ==》 通过中序遍历和后序遍历,重建二叉树
* */
public class ReConstructBinaryTree {
public TreeNode reConstructBinaryTree(int[] preOrder, int[] inOrder)
{
/*
* 输入合法性判断,不能为空,先序和后序的遍历长度要一致
* */
if (preOrder==null || inOrder==null || preOrder.length != inOrder.length) return null;
return constructByPreMid(preOrder, 0, preOrder.length-1, inOrder, 0, inOrder.length-1);
// return constructByMidPos(preOrder, 0, preOrder.length-1, inOrder, 0, inOrder.length-1);
}
/**
*
* @param in 中序遍历
* @param is 中序遍历起始位置
* @param ie 中序遍历终止位置
* @param pos 后序遍历
* @param ps 后序遍历起始位置
* @param pe 后序遍历终止位置
* @return 树的根节点
*/
public TreeNode constructByMidPos(int[] in, int is, int ie, int[] pos, int ps, int pe){
if (is>ie) return null;
//后序遍历最后一个节点为根节点
int value=pos[pe];
//在中序遍历中寻找根节点
int index=is;
while (index<=ie && value!=in[index]) index++;
if (index>ie) throw new RuntimeException("Invalid Input");
//创建当前根节点,并为根节点赋值
TreeNode root = new TreeNode(pos[pe]);
//创建左子树
root.left = constructByMidPos(in,is,index-1,pos,ps,ps+index-1);
//创建右子树
root.right = constructByMidPos(in,index+1,ie, pos, ps+index, pe-1);
return root;
}
/**
*
* @param pre 前序遍历
* @param ps 前序遍历的开始位置
* @param pe 前序遍历的结束位置
* @param in 中序遍历
* @param is 中序遍历的开始位置
* @param ie 中序遍历的结束位置
* @return 树的根节点
*/
private TreeNode constructByPreMid(int[] pre, int ps, int pe, int[] in, int is, int ie)
{
if (ps > pe) return null;
//取前序遍历的第一个节点就是根节点
int value=pre[ps];
//在中序遍历中寻找根节点
int index=is;
while (index<=ie && value!=in[index]) index++;
if (index>ie) throw new RuntimeException("Invalid Input");
//创建当前根节点,并为根节点赋值
TreeNode node = new TreeNode(value);
//递归调用构建当前节点的左子树
node.left = constructByPreMid(pre, ps+1, ps+index-is, in, is, index-1);
//递归调用construct构建当前节点的右子树
node.right = constructByPreMid(pre, ps+index-is+1, pe, in, index+1, ie);
return node;
}
/**
*
* @param pre 前序遍历
* @param in 前序遍历的开始位置
* @param ps 前序遍历的结束位置
* @param pe 中序遍历
* @param is 中序遍历的开始位置
* @param ie 中序遍历的结束位置
* @return 树的根节点
*/
public static TreeNode reConstructBinaryTree(int[] pre, int[] in, int ps, int pe, int is, int ie){
if(ps>pe || is>ie) return null;
if(ps==pe){
return new TreeNode(pre[ps]);
}else{
int curVal = pre[ps];
TreeNode root = new TreeNode(pre[ps]);
int index=0;
for(int i=is;i<=ie;i++){
if(in[i] == curVal){
index = i;
break;
}
}
root.left = reConstructBinaryTree(pre, in, ps+1, ps+index-is, is, index-1);
root.right = reConstructBinaryTree(pre, in, ps+index-is+1, pe, index+1, ie);
return root;
}
}
public static void main(String[] args) {
ReConstructBinaryTree test = new ReConstructBinaryTree();
int[] pre = {1,2,3,4,5,6,7};
int[] in = {3,2,4,1,6,5,7};
TreeNode node = test.reConstructBinaryTree(pre, in);
Traversal.preorder(node);
System.out.println();
Traversal.inorder(node);
}
}