最近一直在复习一些算法及数据结构方面的东西,就找了一个适合找工作笔试的题目,在剑指Offer上刷了几道题目,发现对复习知识点还是很有用的,做到重建二叉树这块。递归传值出了点问题,debug半小时才找出错误,所有还是写篇博客记录一下。也推荐要找工作的伙伴去剑指Offer刷题。
题目描述
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
一看这题目就假如是手写的话,学过数据结构的都知道很简单,一般都是根据前序和中序求后序,或者根据后序和中序求前序,总之要包含中序,二叉树建好只好,其实后序已经出来了,遍历一遍就好了。
思路分析: 前序遍历的第一个数据肯定是根节点,只要找出后序遍历的索引位置就可以确定当前根节点的左右子树,左右子树又是同一个结构,所以用递归非常简单,下面看代码:
TreeNode .class
public class TreeNode { int val; TreeNode left; TreeNode right; TreeNode(int x) { val = x; } @Override public String toString() { return "TreeNode [val=" + val + ", left=" + left + ", right=" + right + "]"; } }
当构造好当前元素之后只需要确定好左右子树即可,主要注意 index-startIn+startPre 这个参数,index-startIn 这是求出了在中序数组的偏移量,再加上startPre就是左子树的pre数组的末元素了,这样就确定好关系了,反复递归就ok了。
public static TreeNode reConstructBinaryTree(int [] pre,int [] in) { return reConstructTree(pre, 0 , pre.length -1, in , 0 , in.length -1 ); } private static TreeNode reConstructTree(int[] pre, int startPre, int endPre, int[] in, int startIn, int endIn) { for(int index = startIn ; index <= endIn ; index++) { if(pre[startPre] == in[index]) { TreeNode treeNode = new TreeNode(in[index]); treeNode.left = reConstructTree(pre,startPre+1,index-startIn+startPre,in,startIn,index-1); treeNode.right = reConstructTree(pre,index-startIn+startPre+1,endPre,in,index+1,endIn); return treeNode; } } return null; }
测试:
private static void foreachBinaryTree(TreeNode treeNode) { if(treeNode != null) { foreachBinaryTree(treeNode.left); foreachBinaryTree(treeNode.right); System.out.println(treeNode.val); } } 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}; TreeNode binaryTree = reConstructBinaryTree(pre,in); foreachBinaryTree(binaryTree); }
我这里后序遍历了一下二叉树。
7 4 2 5 8 6 3 1