剑指Offer系列 重建二叉树

587 阅读3分钟

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

这道题首先我们先回顾下二叉树的相关概念:

二叉树同链表一样属于动态的数据结构

二叉树具有具有唯一根节点
对于每个节点最多可以分出俩个叉
每个节点最多有一个父节点
由上面的概念可以引申出,树是由若干的节点组成,节点连接起来成了树,每个节点由一个数据和俩个指针组成。
创建树就是创建节点,然后连接节点。
二叉树具备天然递归结构 二叉树不一定是“满”的

二叉树的遍历有三种方式:
1)先序遍历:先访问根节点,然后访问左节点最后访问右节点 (根-左-右)
2)中序遍历:先访问左节点,然后访问根节点,最后访问右节点(左-根-右)
3)后序遍历:先访问左节点,然后访问右节点,最后访问根节点(左-右-根)

按照如上遍历规则,我们预测此二叉树的三种遍历结果如下
如果是先序遍历:28-16-13-22-30-29-42
如果是中序遍历:13-16-22-28-29-30-42
如果是后序遍历:13-22-16-29-42-30-28

在具备了上述二叉树的基础知识之后我们就可以回过头来看看这道题

题目提供了此二叉树的先序和中序的数组,由先序的特性 我们可以很明确地知道1乃是最初的根节点,而由中序的特性可以明确的知道 4-7-2乃是根节点1的左子树

所以我们代码这么写

package com.allen.test;

/**
 * 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。 假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
 * 例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6}, 则重建二叉树并返回。
 * 
 * @author lulf
 * @date 2018年11月21日
 */
public class Solution {

	public static void main(String[] args) {
		int[] pre = { 1, 2, 4, 7, 3, 5, 6, 8 };
		int[] in = { 4, 7, 2, 1, 5, 3, 8, 6 };
		TreeNode treeNode = reConstructBinaryTree(pre, in);
	}

	public static TreeNode reConstructBinaryTree(int[] pre, int[] in) {
		return reConstructBinaryTree(pre, 0, pre.length - 1, in, 0, in.length - 1);
	}

	private static TreeNode reConstructBinaryTree(int[] pre, int prestart, int preend, int[] in, int instart, int inend) {
		if(prestart>preend||instart>inend){
			return null;
		}
		TreeNode treeNode=new TreeNode(pre[prestart]);
		for(int i=instart;i<=inend;i++){
			if(pre[prestart]==in[i]){
				treeNode.left=reConstructBinaryTree(pre, prestart+1, prestart+i-instart, in, instart, i-1);
				treeNode.right=reConstructBinaryTree(pre, prestart+i-instart+1, preend, in, i+1, inend);
			}
		}

		return treeNode;
	}
}

采用递归,不断地把响应数组的下标区间值送入层层递归。