题目:
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
二叉树结点定义如下:
/**
* Definition for binary tree
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
思路:
根据先序遍历数组,可以得到树的根节点,根据得到的根节点,去中序数组中找到相应的根节点,因为中序的遍历顺序是左--根--右,可以得到根节点的左子树和右子树的中序遍历数组,这样树的左子树中节点和右子树上节点就确定了。在先序数组中,左子树的先序和左子树的先序也可以确定了。
我们既然已经分别找到了左右子树的前序遍历和中序遍历序列,那么我可以用递归的方法分别继续构建左右子树的左右子树。
解决:
public class Solution {
public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
//判断特殊条件
if(pre == null || in == null || pre.length != in.length){
return null;
}
else{
return reBuildTree(pre,0,pre.length-1,in,0,in.length - 1);
}
}
private TreeNode reBuildTree(int[] pre, int startPre, int endPre, int[] in, int startIn, int endIn){
//判断特殊条件
if(startPre > endPre ||startIn > endIn){
return null;
}
//前序遍历序列的首个元素即为根节点
int root = pre[startPre];
//调用local()方法,获得当前子树中序序列中的根节点位置
int locateRoot = local(root, in, startIn, endIn);
//中序遍历序列中无根节点
if(locateRoot == -1)
return null;
//构造根节点
TreeNode treeNode = new TreeNode(root);
//递归构造左子树,其中左子树的前序遍历序列的结束位置:“locateRoot - startIn”表示左子树的长度,再加上startPre就得到了结束位置的索引
treeNode.left = reBuildTree(pre, startPre + 1, startPre + locateRoot - startIn, in, startIn, locateRoot - 1 );
//递归构造右子树
treeNode.right = reBuildTree(pre, startPre + locateRoot - startIn + 1, endPre, in, locateRoot + 1, endIn);
return treeNode;
}
//在中序序列中查找根元素
private int local(int root, int[] in, int startIn, int endIn){
for (int i = startIn; i <= endIn; i++){
if(root == in[i])
return i;
}
return -1;
}
}