《剑指offer》面试题6:重建二叉树

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

思路:在二叉树的前序遍历序列中,第一个数字总是树的根节点的值。但在中序遍历序列中,根节点的值在序列的中间,左子树的节点的值位于根节点的值的左边,而右子树的节点的值位于根节点的值的右边。

辅助函数:判断异常情况,例如序列为空,不等长等。

功能函数:构建二叉树。

  1. pre的pres的节点记为root节点,在in中找到root节点的位置,根据root在in的片段中所处的位置,判断是否有左子树或者右子树。
  2. 如果存在子树,以左子树为例。根据左子树的长度,在pre中分割出左子树的片段,将片段中第一个值设置为root,进行新一轮的递归。
  3. 递归结束:没有左子树或者右子树。

难点:存在子树时,切割片段中pres,ins,pree,ine的设定。

// 筛选空数列,数列不等长等异常情况
public TreeNode constructTree(int[] pre, int[] in) {
	if (pre.length==0 || in.length==0 || pre.length!=in.length)
		return null;
	return helpconstructTree(pre, in, 0, pre.length-1, 0, in.length-1);
}
// 构建二叉树主函数
public TreeNode helpconstructTree(int[] pre, int[] in, int pres, int pree, int ins, int ine) {
	TreeNode root = new TreeNode(pre[pres]);
	int rootloc = findRoot(in, pre[pres], ins, ine);
	if (rootloc > ins) {	// 有左子树
		int lpree = pres + (rootloc - ins);
		root.left = helpconstructTree(pre, in, pres+1, lpree, ins, rootloc-1);
	}
	if (rootloc < ine) {	// 有右子树
		int rpres = pres + (rootloc - ins) + 1;
		root.right = helpconstructTree(pre, in, rpres, pree, rootloc+1, ine);
	}
	return root;
}
// 找到pre第一个(root)在in的位置
public int findRoot(int[] nums, int num, int s, int e) {
	int i = s;
	for (; i <= e; i++) {
		if (nums[i] == num)
			return i;
	}
	return -1;
}

猜你喜欢

转载自blog.csdn.net/qq_25024883/article/details/81055306