个人记录-LeetCode 105. Construct Binary Tree from Preorder and Inorder Traversal

问题:
Given preorder and inorder traversal of a tree, construct the binary tree.

Note:
You may assume that duplicates do not exist in the tree.

这个问题的条件就是:
给你两个数组,
分别保存一个树先序遍历得到的值,
及该树中序遍历得到的值。

现在要求根据这两个数组,重构出这个树。

解决这个问题,关键是找出数组和树之间的联系。

        5
      /   \
     2     7
    / \   / \
   1   3  6  9

例如上面这颗树,
它先序遍历形成的数组为: 5 2 1 3 7 6 9
它中序遍历形成的数组为: 1 2 3 5 6 7 9

比对数组和树可以发现:
先序遍历的第一个数,对应着根节点的值,
在上述的例子中是5;
在中序遍历后的数组中,5的左侧就根节点的左子树;
5的右侧就是根节点的右子树。

根据中序遍历数组,知道1 2 3构成根节点的左子树后,
我们可以从先序遍历数组中,找出对应的2 1 3。

此时,2 1 3就是根节点左子树的先序遍历;
1 2 3是根节点左子树的中序遍历。
因此,可以按同样的规则,
利用2 1 3和1 2 3构造出左子树。

同理,对于根节点的右子树也可以利用7 6 9和6 7 9构造。

按照上述的思路,就可以递归得到整个树。


代码示例:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        //首先判断preorder和inorder数组是否有效
        if (preorder == null || inorder == null) {
            return null;
        }

        if (preorder.length != inorder.length || preorder.length == 0) {
            return null;
        }

        //preorder的第一个数对应根节点
        int rootVal = preorder[0];
        TreeNode root = new TreeNode(rootVal);

        //判断inorder中,根节点左侧有个数
        int count = 0;
        for (int i : inorder) {
            if (i == rootVal) {
                break;
            }
            ++count;
        }

        if (count > 0) {
            int[] preorderLeft = new int[count];
            int[] inorderLeft = new int[count];

            //preorderLeft保存先序遍历,根节点左侧的值
            System.arraycopy(preorder, 1, preorderLeft, 0, count);

            //inorderLeft保存中序遍历,根节点左侧的值
            System.arraycopy(inorder, 0, inorderLeft, 0, count);

            //递归构造出左子树
            root.left = buildTree(preorderLeft, inorderLeft);
        }

        //得到右子树节点数量
        int rest = preorder.length - count - 1;
        if (rest > 0) {
            int[] preorderRight = new int[rest];
            int[] inorderRight = new int[rest];

            //preorderRight保存先序遍历,根节点右侧的值
            System.arraycopy(preorder, count + 1, preorderRight, 0, rest);

            //inorderRight 保存中序遍历,根节点右侧的值
            System.arraycopy(inorder, count + 1, inorderRight, 0, rest);

            //递归构造出右子树
            root.right = buildTree(preorderRight, inorderRight);
        }

        return root;
    }
}

当然,我这里为了复用buildTree的接口,增加了拷贝的操作,显得比较耗时一些。
也可以新增一个递归接口,传入整个数组及每次生成树用到的序号范围。

你可能感兴趣的:(LeetCode,LeetCode练习记录)