剑指offer--重建二叉树

题外话:

昨天蚊蚊子练车车,蹦蹦哒哒的下车回学校,然后手机就蹦掉了,屏就碎掉了惹,沮丧~
所以今天蚊蚊子为了心情扎了一个双丸子头,然后做了几道剑指offer的题来压压惊~

题意:

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

思路:

前序遍历:根 - 左 - 右
中序遍历:左 - 根 - 右
先看前序,因为前序遍历的第一个节点,就是该树的根。那么在中序中找到该根的位置,设为index;
在中序遍历集合中,位于index之前的属于根的左子树,位于index之后的属于根的右子树;
然后,对左右子树,遍历的调用该过程,就能将树结构还原;

代码:

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
39
40
41
42
43
44
45
46
47
48
49
/**
* 树节点的定义
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Solution {
public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
int value = pre[0];
int length = pre.length;
TreeNode root = new TreeNode(value);
root.left = root.right = null;
if (pre.length == 1) {
return root;
}
int index = 0;
while (in[index] != value)
index++;// 此处还要考虑index==length-1的情况
if (index > 0) {
// 中序中,根节点左边的节点都属于左子树
int[] leftSubPreOrder = new int[index];
for (int i = 0; i < leftSubPreOrder.length; i++) {
leftSubPreOrder[i] = pre[i + 1];
}
int[] leftSubMidOrder = new int[index];
for (int i = 0; i < leftSubMidOrder.length; i++) {
leftSubMidOrder[i] = in[i];
}
root.left = reConstructBinaryTree(leftSubPreOrder, leftSubMidOrder);
}

if (length - index - 1 > 0) {
// 中序中,根节点右边的节点属于右子树
int[] rightSubMidOrder = new int[length - index - 1];
for (int i = 0; i < rightSubMidOrder.length; i++) {
rightSubMidOrder[i] = in[i + index + 1];
}
int[] rightSubPreOrder = new int[length - index - 1];
for (int i = 0; i < rightSubPreOrder.length; i++) {
rightSubPreOrder[i] = pre[i + index + 1];
}
root.right = reConstructBinaryTree(rightSubPreOrder, rightSubMidOrder);
}
return root;
}
}