题目描述
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
先来分析前序和中序遍历得到的结果
在前序遍历列表中第一位为根节点的值,在中序遍历中,根节点左边的值都是根节点的左子树,根节点右边的值都是根节点的右子树。
对于前序遍历如{1,2,4,7,3,5,6,8}的结果,1是该树的根节点的值;在该树的中序遍历结果{4,7,2,1,5,3,8,6}中,{4, 7, 2}是该树的左子树,{5, 3, 8, 6}是该树的右子树。根据中序遍历中左子树和右子树的值,可知在前序遍历中左子树为{2, 4, 7},前序遍历中右子树为{3, 5, 6, 8}。这样将该树分化为左子树和右子树两棵子树。重复上面流程。
综上,已知前序遍历和中序遍历,恢复成一棵树的过程是一个递归的过程。
代码:
public class Solution {
public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
if(pre == null || in == null) {
return null;
}
TreeNode tree = reConstructBinaryTreeCore(pre, in, 0, pre.length - 1, 0, in.length - 1);
return tree;
}
//核心递归函数
public TreeNode reConstructBinaryTreeCore(int[] pre, int[] in, int preStart, int preEnd, int inStart, int inEnd) {
TreeNode tree = new TreeNode(pre[preStart]);
if(preStart == preEnd && inStart == inEnd) {
return tree;
}
int rootSubscript = 0;
while(rootSubscript < inEnd) {
if(pre[preStart] == in[rootSubscript]) {
break;
}
rootSubscript++;
}
int leftTreeLength = rootSubscript - inStart;
int rightTreeLength = inEnd - rootSubscript;
if(leftTreeLength > 0) {
tree.left = reConstructBinaryTreeCore(pre, in, preStart + 1, preStart + leftTreeLength, inStart, rootSubscript - 1);
}
if(rightTreeLength > 0) {
tree.right = reConstructBinaryTreeCore(pre, in, preStart + leftTreeLength + 1, preEnd, rootSubscript + 1,inEnd);
}
return tree;
}
//树的先序遍历,用来检测代码
public void test(TreeNode tree) {
if(tree != null) {
System.out.print(tree.val + ", ");
test(tree.left);
test(tree.right);
}
}
public static void main(String[] args) {
int[] pre = {1,2,4,7,3,5,6,8};
int[] in = {4,7,2,1,5,3,8,6};
Solution s = new Solution();
TreeNode tree = s.reConstructBinaryTree(pre, in);
s.test(tree);
}
}