程序员社区

LeetCode-105-从前序与中序遍历序列构造二叉树

LeetCode-105-从前序与中序遍历序列构造二叉树

105. 从前序与中序遍历序列构造二叉树

难度中等

根据一棵树的前序遍历与中序遍历构造二叉树。

注意:
你可以假设树中没有重复的元素。

例如,给出

前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]

返回如下的二叉树:

    3
   / \
  9  20
    /  \
   15   7

解法、递归 分治
先序遍历的顺序是根节点,左子树,右子树。中序遍历的顺序是左子树,根节点,右子树。

所以我们只需要根据先序遍历得到根节点,然后在中序遍历中找到根节点的位置,它的左边就是左子树的节点,右边就是右子树的节点。

生成左子树和右子树就可以递归的进行了。

preorder = [3,9,20,15,7]
inorder = [9,3,15,20,7]
首先根据 preorder 找到根节点是 3
    
然后根据根节点将 inorder 分成左子树和右子树
左子树
inorder [9]

右子树
inorder [15,20,7]

把相应的前序遍历的数组也加进来
左子树
preorder[9] 
inorder [9]

右子树
preorder[20 15 7] 
inorder [15,20,7]

现在我们只需要构造左子树和右子树即可,成功把大问题化成了小问题
然后重复上边的步骤继续划分,直到 preorder 和 inorder 都为空,返回 null 即可


事实上,我们不需要真的把 preorder 和 inorder 切分了,只需要用分别用两个指针指向开头和结束位置即可。注意下边的两个指针指向的数组范围是包括左边界,不包括右边界。


class Solution {
    public static TreeNode buildTree(int[] preorder, int[] inorder) {
        HashMap<Integer, Integer> map = new HashMap<>();
        for (int i = 0; i < inorder.length; i++) {
            map.put(inorder[i], i);
        }
        return f(preorder, 0, preorder.length - 1, inorder, 0, inorder.length - 1, map);
    }

    public static TreeNode f(int[] pre, int L1, int R1, int[] in, int L2, int R2, HashMap<Integer, Integer> map) {
        if (L1 > R1) {
            return null;
        }
        TreeNode head = new TreeNode(pre[L1]);
        if (L1 == R1) {
            return head;
        }
        int findIndex = map.get(pre[L1]);
        head.left = f(pre, L1 + 1, L1 + findIndex - L2, in, L2, findIndex - 1, map);
        head.right = f(pre, L1 + findIndex - L2 + 1, R1, in, findIndex + 1, R2, map);
        return head;
    }
}
LeetCode-105-从前序与中序遍历序列构造二叉树插图
image-20210607093236437
赞(0) 打赏
未经允许不得转载:IDEA激活码 » LeetCode-105-从前序与中序遍历序列构造二叉树

一个分享Java & Python知识的社区