剑指Offer之重建二叉树

题目描述

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

分析:

在二叉树的前序遍历中,第一个数字总是树的根节点的值。但在中序遍历序列中,根节点的值在序列的中间,左子树的值位于根节点的左边,而右子树的节点的值位于根节点的值得右边。因此我们需要扫描中序遍历,才能找到根节点的值。

如下图所示,前序遍历序列的第一个数字1就是根节点的值。扫描中序遍历序列,就能确定根节点的值得位置。根据中序遍历特点,在根节点的值1前面的3个数字都是左子树节点的值,位于1后面的数字都是右子树节点的值。

 

 由于在中序遍历中,有3个数字是左子树节点的值,因此左子树总共有3个左子节点。同样,在前序遍历中,根节点后面的3个数字就是3个左子树节点的值,再后面的所有数字都是右节点的值。这样我们就在前序遍历和中序遍历两个序列中,分别找到了左右子树对应的子序列。

Java代码

 1 import java.util.LinkedList;
 2 import java.util.Queue;
 3 import java.util.Scanner;
 4 
 5 /**
 6  * Created by Feng on 2017/5/1.
 7  * 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
 8  * 例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
 9  */
10 public class ReConstructBinaryTree {
11     public static void main(String[] args) {
12         Scanner sc = new Scanner(System.in);
13         while (sc.hasNext()) {
14             int n = sc.nextInt();//二叉树的节点数
15 
16             int[] preorder = new int[n];//二叉树先序遍历
17             for (int i = 0; i < n; i++) {
18                 preorder[i] = sc.nextInt();
19             }
20 
21             int[] inorder = new int[n];//二叉树中序遍历
22             for (int i = 0; i < n; i++) {
23                 inorder[i] = sc.nextInt();
24             }
25 
26             TreeNode root = reConstruct(preorder, inorder);
27             System.out.print(root.val + " ");
28 
29             //使用对列输出重构的二叉树
30             Queue<TreeNode> queue = new LinkedList<>();
31             queue.add(root);
32 
33             //利用对列先进先出的特点
34             while (!queue.isEmpty()) {
35                 TreeNode node = queue.poll();
36                 if (node.left != null) {
37                     System.out.print(node.left.val + " ");
38                     queue.add(node.left);
39                 }
40                 if (node.right != null) {
41                     System.out.print(node.right.val + " ");
42                     queue.add(node.right);
43                 }
44             }
45         }
46     }
47 
48     private static TreeNode reConstruct(int[] preorder, int[] inorder) {
49         if (preorder == null || inorder == null) {
50             return null;
51         }
52 
53         return reConstructCore(preorder, 0, preorder.length - 1, inorder, 0, inorder.length - 1);
54     }
55 
56     private static TreeNode reConstructCore(int[] preorder, int startPre, int endPre,
57                                             int[] inorder, int startIn, int endIn) {
58         if (startPre > endPre || startIn > endIn) {
59             return null;
60         }
61 
62         //获取根节点,先序遍历的第一个值即根节点
63         TreeNode root = new TreeNode(preorder[startPre]);
64 
65         for (int i = startIn; i <= endIn; i++) {
66             if (inorder[i] == preorder[startPre]) {
67                 //构建左子树
68                 root.left = reConstructCore(preorder, startPre + 1, startPre + i - startIn,
69                         inorder, startIn, i - 1);
70                 //构建右子树
71                 root.right = reConstructCore(preorder, i - startIn + startPre + 1, endPre,
72                         inorder, i + 1, endIn);
73             }
74         }
75 
76         return root;
77     }
78 
79 
80 }
81 
82 class TreeNode {
83     int val;
84     TreeNode left;
85     TreeNode right;
86 
87     TreeNode(int x) {
88         val = x;
89     }
90 }

 

posted @ 2017-05-04 09:53  凌风1205  阅读(177)  评论(0编辑  收藏  举报
//一下两个链接最好自己保存下来,再上传到自己的博客园的“文件”选项中