题目: 输入二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历与中序遍历中都不包含重复的数字。
解题思路:
- 二叉树的前序遍历中,第一个数字总是根节点的值;中序遍历中根节点的值在中间,将左右子树分开了;
- 首先根据前序遍历得到根节点的值,然后根据中序遍历和根节点的值得到左右子树的前序遍历和中序遍历序列;
- 递归构建左子树和右子树;
代码实现:
//二叉树的节点
static class BinaryTreeNode{
int value;
BinaryTreeNode left;
BinaryTreeNode right;
BinaryTreeNode(int value){
this.value=value;
this.left=null;
this.right=null;
}
}
/**
* 根据二叉树的前序遍历和中序遍历的结果,重建该二叉树
* @param preOrder 前序遍历序列
* @param inOrder 中序遍历序列
* @return
*/
public static BinaryTreeNode construct(int[] preOrder,int[] inOrder){
if (preOrder==null||inOrder==null||preOrder.length<0||inOrder.length<0)
return null;
return constructCore(preOrder,inOrder);
}
//重建二叉树的核心代码
private static BinaryTreeNode constructCore(int[] preOrder,int[] inOrder){
//前序遍历序列的第一个数字是根节点的值
int rootValue=preOrder[0];
BinaryTreeNode root=new BinaryTreeNode(rootValue);
//如果中序遍历与前序遍历中只有一个值,那就是当前子树的根节点
if (preOrder.length==1||inOrder.length==1)
return root;
int inOrderRootIndex=0;
int preOrderRootIndex=0;
//在中序遍历中找到根结点的值对应的下标
for (int i = 0; i < inOrder.length; i++) {
if (inOrder[i]==rootValue){
inOrderRootIndex=i;
break;
}
}
//构建左子树
if (inOrderRootIndex>0){
//newPreOrder和newInOrder是左子树的前序遍历和中序遍历序列
int[] newPreOrder=Arrays.copyOfRange(preOrder,preOrderRootIndex+1,inOrderRootIndex+1);
int[] newInOrder=Arrays.copyOfRange(inOrder,0,inOrderRootIndex);
root.left=constructCore(newPreOrder,newInOrder);
}
//构建右子树
if (inOrder.length-inOrderRootIndex-1>0){
//newPreOrder和newInOrder是右·子树的前序遍历和中序遍历序列
int[] newPreOrder=Arrays.copyOfRange(preOrder,inOrderRootIndex+1,preOrder.length);
int[] newInOrder=Arrays.copyOfRange(inOrder,inOrderRootIndex+1,inOrder.length);
root.right=constructCore(newPreOrder,newInOrder);
}
return root;
}