剑指Offer_4

题目

重建二叉树

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

解题思路

前序遍历和中序遍历的数组

通过前序遍历数组找各子树的根节点,中序遍历数组找各子树的左右子树包含的节点

根据图上的两个数组,我们可以知道该二叉树的根节点是1,左子树包含的节点有2,4,7,同理可得右子树节点们。

那么现在就可以在2, 4, 7继续上述的操作,进行递归操作,同理可得右子树。

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
30
31
32
33
34
35
36
37
38
/**
* 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) {
if(pre == null || in == null){
return null;
}
return helper(pre, 0, pre.length-1, in, 0, in.length-1);
}
public TreeNode helper(int []pre, int pre_lo, int pre_hi, int []in, int in_lo, int in_hi){
if(pre_lo > pre_hi || in_lo > in_hi){
return null;
}
TreeNode root = new TreeNode(pre[pre_lo]);
//for循环,目的是找出子树根节点在中序遍历数组中的位置,以此来分割左右子树
for(int i = in_lo; i <= in_hi; ++i){
if(pre[pre_lo] == in[i]){
//pre_lo为子树根节点,并且是前序遍历数组的第一位
//i为子树根节点在中序遍历数组的位置
//以此来划分两个数组的左右子树节点们
//前序遍历数组:左子树[pre_lo+1, i-in_lo+pre_lo], 右子树[i-in_lo+1+pre_lo, pre_hi]
//中序遍历数组:左子树[in_lo, i-1], 右子树[i+1, in_hi]
root.left = helper(pre, pre_lo+1, i-in_lo+pre_lo, in, in_lo, i-1);
root.right = helper(pre, i-in_lo+1+pre_lo, pre_hi, in, i+1, in_hi);
}
}
return root;
}
}