您的位置:首页 > Web前端

剑指Offer之重建二叉树

2017-05-04 09:53 369 查看

题目描述

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{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代码

import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

/**
* Created by Feng on 2017/5/1.
* 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
* 例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
*/
public class ReConstructBinaryTree {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
int n = sc.nextInt();//二叉树的节点数

int[] preorder = new int
;//二叉树先序遍历
for (int i = 0; i < n; i++) {
preorder[i] = sc.nextInt();
}

int[] inorder = new int
;//二叉树中序遍历
for (int i = 0; i < n; i++) {
inorder[i] = sc.nextInt();
}

TreeNode root = reConstruct(preorder, inorder);
System.out.print(root.val + " ");

//使用对列输出重构的二叉树
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);

//利用对列先进先出的特点
while (!queue.isEmpty()) {
TreeNode node = queue.poll();
if (node.left != null) {
System.out.print(node.left.val + " ");
queue.add(node.left);
}
if (node.right != null) {
System.out.print(node.right.val + " ");
queue.add(node.right);
}
}
}
}

private static TreeNode reConstruct(int[] preorder, int[] inorder) {
if (preorder == null || inorder == null) {
return null;
}

return reConstructCore(preorder, 0, preorder.length - 1, inorder, 0, inorder.length - 1);
}

private static TreeNode reConstructCore(int[] preorder, int startPre, int endPre,
int[] inorder, int startIn, int endIn) {
if (startPre > endPre || startIn > endIn) {
return null;
}

//获取根节点,先序遍历的第一个值即根节点
TreeNode root = new TreeNode(preorder[startPre]);

for (int i = startIn; i <= endIn; i++) {
if (inorder[i] == preorder[startPre]) {
//构建左子树
root.left = reConstructCore(preorder, startPre + 1, startPre + i - startIn,
inorder, startIn, i - 1);
//构建右子树
root.right = reConstructCore(preorder, i - startIn + startPre + 1, endPre,
inorder, i + 1, endIn);
}
}

return root;
}

}

class TreeNode {
int val;
TreeNode left;
TreeNode right;

TreeNode(int x) {
val = x;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: