LeetCode105,根据前序、中序遍历结果,构建二叉树。思路与Java解答

LeetCode105

关键思路:

1. 前序遍历序列的第一个数,即为根。

2. 前序遍历的整个序列可以分为3个连续部分:根,左子树,右子树。

3. 中序遍历的整个序列可以分为3个连续部分:左子树,根,右子树。


有了上面3个思路,开始模拟一下程序:

1. 根据preorder序列,找到root

2. 根据root,在inorder中确定左右子树

3. 根据inorder中左右子树的长度,在preorder中确定左右子树

4. 递归子树的前序、中序序列,为root构建左右子树


递归实现如下:

/**
 * 根据前序、中序遍历,构建二叉树
 * 关键思路:
 * 前序、中序遍历结果,都分为三个连续区域:
 * 前序:根,左子树,右子树
 * 终须:左子树,根,右子树
 * 
 * @author line
 * @date 2019年2月17日 下午8:46:50
 */
public class Solution105 {

	/**
	 * 1. 根据preorder确定root
	 * 2. 根据root和inorder确定左右子树
	 * 3. 分别挑出左右子树,重复1.
	 */
	public TreeNode buildTree(int[] preorder, int[] inorder) {
		if (preorder == null || preorder.length == 0)
			return null;
		return build(preorder, 0, preorder.length - 1, inorder, 0, inorder.length - 1);
	}

	/**
	 * 递归构建左右子树
	 */
	private TreeNode build(int[] pre, int preStart, int preEnd, int[] in, int inStart, int inEnd) {
		TreeNode root = new TreeNode(pre[preStart]); // 这里写成这样,就要提前判断空指针!

		int pos = findRoot(root.val, in, inStart, inEnd);
		int leftLen = pos - inStart; // 左子树长度
		int rightLen = inEnd - pos; // 右子树长度

		if (leftLen > 0)
			root.left = build(pre, preStart + 1, preStart + leftLen, in, inStart, inStart + leftLen - 1);
		if (rightLen > 0)
			root.right = build(pre, preEnd - rightLen + 1, preEnd, in, inEnd - rightLen + 1, inEnd);

		return root;
	}

	/**
	 * 根据传入的root.val,寻找root在inorder序列中的位置,以此找出左右子树
	 */
	private int findRoot(int rootVal, int[] in, int inStart, int inEnd) {
		for (int i = inStart; i <= inEnd; i++) {
			if (in[i] == rootVal)
				return i;
		}
		return -1; // ERROR! 题目没有问题的话不应该走到这里
	}
}

后序、中序也一样,就不做了。呵呵。

有啥错误的地方还请大神指正!!


扩展一下:

1. 前序、后序能否唯一构建一颗二叉树?

不能。因为不能够根据根的位置确定左右子树,比如斜树的情况。

2. 前序遍历结果相同的树,就一定相同吗?

不一定。可以归结到仅根据前序遍历能否唯一构建一颗二叉树的问题。中、后序同理。

你可能感兴趣的:(LeetCode)