二叉树--前中后序两两结合构建二叉树

题解

  1. 你可以假设树中没有重复的元素。这句话代表什么呢?

这样可以保证结点的数值可以在中序遍历数组中唯一确定,这样还原出的二叉树是唯一确定的

  1. 根据(先序+中序)或者(中序+后序)可以唯一确定二叉树,根据(先序+后序)无法唯一确定二叉树,但是如果一棵二叉树除了叶子结点外,其他所有结点都有左子和右子,这样的树可以根据(先序+后序)唯一确定。

先序+中序确定二叉树(leetcode 105)

思路

  1. 先序数组中最左边的值就是树的根节点的值,记为h,并用h生成头节点,记为head。然后在中序数组找到h,设位置为i。在中序数组中,i左边的数组就是头节点左子树的中序数组,假设长度为l,则左子树的先序数组就是先序数组中h往右长度为l的数组。

  2. 用左子树的先序和中序数组,递归构建左子树,返回的头节点为left

  3. i右边的数组就是头节点右子树的中序数组,假设长度为r。先序数组中右侧等长的部分就是头节点右子树的先序数组

  4. 用右子树的先序和中序数组,递归构建右子树,返回的右节点记为right

  5. 将head的左子,右子设为left,right,返回head,过程结束。

在中序数组中找到位置i可以用哈希表实现。

时间复杂度:O(n)
空间复杂度:O(n)

代码

    public TreeNode buildTree(int[] preorder, int[] inorder) {
        int preLen = preorder.length;
        int inLen = inorder.length;
        if (preLen != inLen){
            throw new RuntimeException("Error");
        }

        Map<Integer, Integer> map = new HashMap<>();
        for (int i = 0; i < inLen; i++){
            map.put(inorder[i], i);
        }

        return helper(preorder, 0, preLen - 1, inorder, 0, inLen - 1, map);
    }

    public TreeNode helper(int[] preorder, int preLeft, int preRight,
                           int[] inorder, int inLeft, int inRight,
                           Map<Integer, Integer> map){
        if (preLeft > preRight || inLeft > inRight){
            return null;
        }
        int rootVal = preorder[preLeft];
        TreeNode root = new TreeNode(rootVal);
        int index = map.get(rootVal);

        root.left = helper(preorder, preLeft + 1, index - inLeft + preLeft,
                            inorder, inLeft, index - 1, map);
        root.right = helper(preorder, index - inLeft + preLeft + 1, preRight,
                            inorder, index + 1, inRight, map);
        return root;
    }

后序+中序确定二叉树(leetcode 106)

和第一种类似,后序数组中头节点是后序数组最右的值,用后序最右的值划分中序数组即可。时空间复杂度也和之前的一样。

    public TreeNode buildTree(int[] inorder, int[] postorder) {
        int inLen = inorder.length;
        int posLen = postorder.length;
        if (inLen != posLen){
            throw new RuntimeException("Error!");
        }
        Map<Integer, Integer> map = new HashMap<> ();
        for (int i = 0; i < inLen; i++) {
            map.put(inorder[i], i);
        }
        return helper(inorder, 0, inLen - 1, postorder, 0, posLen - 1, map);
    }
    
    public TreeNode helper(int[] inorder, int inLeft, int inRight,
                           int[] postorder, int postLeft, int postRight,
                           Map<Integer, Integer> map){
        if (inLeft > inRight || postLeft > postRight){
            return null;
        }
        int rootVal = postorder[postRight];
        TreeNode root = new TreeNode(rootVal);
        int index = map.get(rootVal);
        root.left = helper(inorder, inLeft, index - 1,
                            postorder, postLeft, postLeft + index - inLeft - 1,
                            map);
        root.right = helper(inorder, index + 1, inRight,
                            postorder, postLeft + index - inLeft, postRight - 1,
                            map);
        return root;
    }

先序+后序构建二叉树(leetcode 889)

待施工

posted @ 2020-07-19 18:16  swifthao  阅读(209)  评论(0编辑  收藏  举报
Live2D