重建二叉树

题目:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

分析

首先要了解树的几种遍历方式:

  • 先序遍历:根结点→左子结点→右子结点
  • 中序遍历:左子结点→根结点→右子结点
  • 后序遍历:左子结点→右子结点→根结点

  由题目已知到先序遍历和中序遍历,根据先序遍历和中序遍历的特点,先序遍历的第一个值是根结点,由此可以在中序遍历中找到这个根结点,再由中序遍历的特点,中序遍历中根结点的左边是根结点的左子树的中序遍历序列,右边是根结点的右子树的中序遍历序列。

  如下图所示,先序遍历序列为{1,2,4,7,3,5,6,8},中序遍历序列{4,7,2,1,5,3,8,6}。由先序遍历第一个可知道根结点为1。再到中序遍历中找到1,则它左边的{4,7,2}和右边的{5,3,8,6},分别是它左右子树的中序遍历,然后在看先序遍历序列中的{2,4,7}和{3,5,6,8},分别是根结点的左右子树的先序遍历。

这样问题就被划分成了:

  1. 已知先序遍历序列{2,4,7}和中序遍历{4,7,2}重构二叉树;
  2. 已知先序遍历序列{3,5,6,8}和中序遍历{5,3,8,6}重构二叉树;

然后这两个问题的解法就依次类推了,显而易见,这里需要用到递归的思想来实现重构二叉树。

0 1 2 3 4 5 6 8
1 2 4 7 3 5 6 8
4 7 2 1 5 3 8 6

代码实现

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/**
* Definition for binary tree
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Solution {
public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
TreeNode root=reConstructBinaryTree(pre,0,pre.length-1,in,0,in.length-1);
return root;
}
private TreeNode reConstructBinaryTree(int [] pre,int startPre,int endPre,int [] in,int startIn,int endIn) {

if(startPre>endPre||startIn>endIn)
return null;
TreeNode root=new TreeNode(pre[startPre]);

for(int i=startIn;i<=endIn;i++)
if(in[i]==pre[startPre]){
root.left=reConstructBinaryTree(pre,startPre+1,startPre+i-startIn,in,startIn,i-1);
root.right=reConstructBinaryTree(pre,i-startIn+startPre+1,endPre,in,i+1,endIn);
}

return root;
}
}

总结

  1. 递归的思想。参考:java递归算法实现
  2. 二叉树的几种遍历方式,以及每个遍历序列的特点。
  3. 思考:如果已知先序遍历序列和后序遍历序列又该如何重构二叉树?