题目描述
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。
首先是要了解前序,中序遍历两个对树遍历的结果是什么结构。
前序遍历:根节点--(根节点左子树所有节点)--(根节点右子树所有节点){1,2,4,7,3,5,6,8}
中序遍历:(根节点左子树所有节点)--根节点--(根节点右子树所有节点){4,7,2,1,5,3,8,6}
因此,前序遍历结果中的第一个元素就是根节点。然后在中序中做对比,则根节点的左边元素是{2,4,7},那么2又是根节点,去中序中找,则发现{4,7,2},因此{4,7}都是2的左子树,2右子树为空。同理判断出4是2的左子树节点,而中序中为{4,7},因此4的左子树为空,7是4的右子树。到此为止1的左子树已经分析完了。同理,{3,5,6,8}按这个原理分析。得到3是右子树根节点(3又是1的右子节点),对比中序得到3左子节点是5,右边是{6,8},而6又是根,对比中序得到8在6的左边。
按照这个逻辑写代码。
思路,由于每次都可以确认一个子树的根节点,所以肯定可以使用递归。需要捋清的是,首先是找到根节点(就是前序数组的首元素),然后在中序中找到其位置,然后中序数组以这个位置为界限,左边调用递归,右边调用递归。在每次递归中,都找到的是根节点。
如:root.left=reConstruct(..);
reConstruct返回的是当前给入的树的根节点,所以root.left拿到了自己的左节点(左子树的根节点)
而递归终止的条件,就是传入的数组的索引出问题(首元素)
public class Solution { public TreeNode reConstructBinaryTree(int [] pre,int [] in) { TreeNode root=reConstruct(pre,0,pre.length-1,in,0,in.length-1); //传过去一个两个数组以及这个数组的首尾索引 return root; } //前序遍历{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6} public TreeNode reConstruct(int[] pre,int sP,int eP,int[] in,int sI,int eI) { //startPre和endpre以及startIn和endIn的缩写 分别代表传入数组的首尾位置的索引 if(sP>eP||sI>eI) //递归结束标志(也可加入其他健壮性语句) return null; //满足这两个条件,说明数组首元素索引大于尾元素索引,因此不用判断数组长度为0和数组是否为空 //个人理解:判断数组长度为0和数组为空是使代码更健壮,而非一定要写上。 TreeNode root=new TreeNode(pre[sP]); //找到pre的首节点,就是传过来的树的根 for(int i=sI;i<=eI;i++) //遍历传过来的中序,找到根节点。 if(in[i]==pre[sP]){ //其左边的是子树,调用递归。右边的是右子树,调用递归 root.left=reConstruct(pre,sP+1,sP+i-sI,in,sI,i-1); root.right=reConstruct(pre,i-sI+sP+1,eP,in,i+1,eI); break;//找到根节点在中序的位置就可以了,可以提前退出。 } return root; } }