跳转至

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

问题描述#

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

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

例如,给出

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

返回如下的二叉树:

    3
   / \
  9  20
    /  \
   15   7

解题思路#

preorder 中的每个值都作为新的根结点,在 inorder 中,该值的位置确定了左右子树的界限。

  • \(\text{preorder} = [\boxed{3},9,20,15,7], \text{inorder}=[\underbrace{9}_{左子树},\underbrace{\boxed{3}}_{根结点}, \underbrace{15,20,7}_{右子树}]\)

  • \(\text{preorder} = [\boxed{9}], \text{inorder}=[\underbrace{\text{None}}_{左子树},\underbrace{\boxed{9}}_{根结点}, \underbrace{\text{None}}_{右子树}]\)

  • \(\text{preorder} = [\boxed{20},15,7], \text{inorder}=[\underbrace{15}_{左子树},\underbrace{\boxed{20}}_{根结点}, \underbrace{7}_{右子树}]\)

  • \(\text{preorder} = [\boxed{15}], \text{inorder}=[\underbrace{\text{None}}_{左子树},\underbrace{\boxed{15}}_{根结点}, \underbrace{\text{None}}_{右子树}]\)

  • \(\text{preorder} = [\boxed{7}], \text{inorder}=[\underbrace{\text{None}}_{左子树},\underbrace{\boxed{7}}_{根结点}, \underbrace{\text{None}}_{右子树}]\)

根据 \(\texttt{preorder}\) 根结点确定 \(\texttt{inorder}\) 中的根结点的位置,进而确定下一步中左右子树的范围以及根结点位置。

在先序遍历中,某个结点的 左子树的根结点 就在该结点之后,而该结点的 右子树的根结点 则在该结点加上 左子树结点数量 之后。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
class Solution:
    def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode:
        index = {x: i for i, x in enumerate(inorder)}

        def dfs(preorder_root: int, inorder_left: int, inorder_right: int) -> TreeNode:
            if inorder_left > inorder_right: return None

            root = TreeNode(preorder[preorder_root])
            inorder_root = index[preorder[preorder_root]]

            root.left = dfs(preorder_root + 1, inorder_left, inorder_root - 1)
            root.right = dfs(preorder_root + (inorder_root - inorder_left) + 1, inorder_root + 1, inorder_right)

            return root

        return dfs(0, 0, len(inorder) - 1)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Solution {
public:
    unordered_map<int, int> index;

    TreeNode* dfs(vector<int> &preorder, vector<int> &inorder, int preorder_root, int inorder_left, int inorder_right) {
        if (inorder_left > inorder_right) return nullptr;

        auto root = new TreeNode(preorder[preorder_root]);
        int inorder_root = index[preorder[preorder_root]];

        root->left = dfs(preorder, inorder, preorder_root + 1, inorder_left, inorder_root - 1);
        // inorder_root - inorder_left 为左子树元素个数
        root->right = dfs(preorder, inorder, preorder_root + (inorder_root - inorder_left) + 1, inorder_root + 1, inorder_right);

        return root;
    }

    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        int n = inorder.size();

        for (int i = 0; i < n; ++i) {
            index[inorder[i]] = i;
        }

        return dfs(preorder, inorder, 0, 0, n - 1);
    }
};

时间复杂度\(\mathcal{O}(n)\)
空间复杂度\(\mathcal{O}(n)\)

返回顶部

在手机上阅读