问题
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树。
思路
首先找到先序遍历的第一个节点,就是根节点,然后在中序遍历中找到根节点。此时,根节点左右两边,分别是左右子树的中序遍历。再对于先序遍历,从第二个节点开始,到中序遍历中左子树的长度,就是左子树的先序遍历。同理,右子树也是一样,这是一个递归过程。
public BinaryTreeNode getTheRoot(List<Integer> preorder, List<Integer> inorder, int count) { //前序排列中的第一个数字为当前根节点的值 int rootValue = preorder.get(0); BinaryTreeNode root = new BinaryTreeNode(); root.value = rootValue; //如果count=1,则表示当前节点为叶子节点,直接返回 if (count == 1) { return root; } // 根节点的值在中序排列中的位置 int index = 0; for (int i : inorder) { if (i == rootValue) { break; } index++; } //表示在中序排列中没有找到根节点的值,则表示前序排列或者中序排列的输入有误 if (index == count) { throw new RuntimeException("错误的排序输入!"); } //如果index > 0,则表示当前有左子树 if (index > 0) { // 左子树的前序排列从当前前序排列的第二个值(去掉当前根节点)开始,包含左子树个数个值(index) List<Integer> startPreorder = preorder.subList(1, (index + 1)); // 左子树的中排列从当前中序排列的第一个值开始,直到根节点的位置(不包含根节点) List<Integer> startInorder = inorder.subList(0, index); root.left = getTheRoot(startPreorder, startInorder, index); } //如果index > 0,则表示当前有有子树 if (index < count - 1) { List<Integer> endPreorder = preorder.subList((index + 1), count); List<Integer> endInorder = inorder.subList((index + 1), count); //这里为什么是count - index - 1 大家可以画图思考一下 root.right = getTheRoot(endPreorder, endInorder, (count - index - 1)); } return root; }
总结
首先要熟悉二叉树的前序遍历,中序遍历,以及后序遍历,再加上递归的思想,就可以实现。