1.题目:
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
2.思路:
根据中序遍历和前序遍历可以确定二叉树,具体过程为:
根据前序序列第一个结点确定根结点 根据根结点在中序序列中的位置分割出左右两个子序列 对左子树和右子树分别递归使用同样的方法继续分解
例如:
前序序列{1,2,4,7,3,5,6,8} = pre
中序序列{4,7,2,1,5,3,8,6} = in
根据当前前序序列的第一个结点确定根结点,为 1 找到 1 在中序遍历序列中的位置,为 in[3] 切割左右子树,则 in[3] 前面的为左子树, in[3] 后面的为右子树 则切割后的左子树前序序列为:{2,4,7},切割后的左子树中序序列为:{4,7,2};切割后的右子树前序序列为:{3,5,6,8},切割后的右子树中序序列为:{5,3,8,6} 对子树分别使用同样的方法分解
方法一:使用类库复制数组,不大好
import java.util.Arrays; public class Solution { public TreeNode reConstructBinaryTree(int [] pre,int [] in) { if(pre.length==0||in.length==0){//判空 return null; } TreeNode node=new TreeNode(pre[0]);//找到根节点,一定在前序遍历的第一个 for(int i=0;i<in.length;i++){//遍历 if(pre[0]==in[i]){//找到中序遍历中的根节点位置,拆分为两部分 node.left=reConstructBinaryTree(Arrays.copyOfRange(pre,1,i+1),Arrays.copyOfRange(in,0,i));//递归左子树 node.right=reConstructBinaryTree(Arrays.copyOfRange(pre,i+1,pre.length),Arrays.copyOfRange(in,i+1,in.length));//递归右子树 break;//找到则跳出 } } return node;//返回 } }
方法二:也是使用分治算法,利用递归进行重建
推算:
import java.util.*; public class Solution { HashMap<Integer,Integer> dic=new HashMap<>(); int[] pre; public TreeNode reConstructBinaryTree(int [] pre,int [] in) { if(pre.length!=in.length) return null;//前序遍历长度与中序遍历长度一定向等 for(int i=0;i<in.length;i++){//先将中序遍历存入map中,这样以后就不用再遍历了 dic.put(in[i],i); } this.pre=pre; return rebuildTree(0,0,pre.length-1); } private TreeNode rebuildTree(int root,int inLeft,int inRight){ if(inLeft>inRight) return null; TreeNode node=new TreeNode(pre[root]);//构建头节点 int index=dic.get(node.val);//通过map找到在中序遍历中的未知,进行左右子树的拆分 node.left=rebuildTree(root+1,inLeft,index-1); node.right=rebuildTree(index-inLeft+root+1,index+1,inRight); return node; } }