【题目描述】
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
输入
[1,2,3,4,5,6,7],[3,2,4,1,6,5,7]
返回值
{1,2,5,3,4,6,7}
思路
先顺数组的第一个值一定是二叉树的根节点,根节点在中序数组中将中序数组分为两个部分,左边的部分数组left为该节点的左子树上的节点,右边的部分数组right为该节点在右子树上的结点,分别在先序数组中找到在left和right中元素第一次出现的值,将该节点作为左右子树的根节点,再重复上述的操作,直到left和right为空为止,结束。很明显使用递归的解决问题。
给出二叉树类的构造:
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
首先,定义方法findIndex(int[] arr, int a)找出a在arr中的index,这里是为了找出根节点在中序数组中的index,好将中序数组分为left和right。
public static int findIndex(int[] arr, int a){
int index = 0;
if (arr[0] == a) return 0;
for (int i = 1; i < arr.length; i++){
if (arr[i] == a){
index = i;
break;
}
}
return index;
}
然后,定义leftInterval(int[] in, int index)和rightInterval(int[] in, int index)方法,根据index将中序数组分为左右区间。
//左区间
public static int[] leftInterval(int[] in, int index){
int len = index;
int[] left = new int[len];
for (int i = 0; i < len; i++){
left[i] = in[i];
}
return left;
}
// 右区间
public static int[] rightInterval(int[] in, int index){
int len = in.length - index - 1;
int[] right = new int[len];
for (int i = 0; i < len; i++){
right[i] = in[index + i + 1];
}
return right;
}
再定义方法preFindIn(int[] pre, int[] in),找到输入的部分中序数组,及left和right,把它们按照在先序数组中出现的顺序排列。
public static int[] preFindIn(int[] pre, int[] in){
int preFirst = 0;
int len = in.length;
int[] preOfIn = new int[len];
for (int i = 0; i < pre.length; i++){
if (preFirst != 0) break;
for (int j = 0; j < len; j++){
if (pre[i] == in[j]){
preFirst = i;
break;
}
}
}
for (int i = preFirst; i < preFirst + len; i++) {
preOfIn[i-preFirst] = pre[i];
}
return preOfIn;
}
最终给出重建二叉树的方法reConstructBinaryTree(int [] pre,int [] in)。
public static TreeNode reConstructBinaryTree(int [] pre,int [] in) {
if (pre.length == 0 || in.length == 0){
return null;
}
int root = pre[0]; // 先序序列的第一个值是根节点
TreeNode tree = new TreeNode(root);
int rootOfIn = findIndex(in, root); // 根节点在中序序列中的index
int[] leftIn = leftInterval(in, rootOfIn); // 左区间
int[] rightIn = rightInterval(in, rootOfIn); // 右区间
TreeNode left = reConstructBinaryTree(preFindIn(pre, leftIn), leftIn);
TreeNode right = reConstructBinaryTree(preFindIn(pre, rightIn), rightIn);
/* System.out.println("leftIn" + Arrays.toString(leftIn));
System.out.println("rightIn" + Arrays.toString(rightIn));*/
tree.left = left;
tree.right = right;
return tree;
}