Leetcode No.105 construction of binary tree from preorder and inorder traversal sequences

1, Title Description

According to the preorder traversal and inorder traversal of a tree, a binary tree is constructed.

be careful: You can assume that there are no duplicate elements in the tree.

For example, give

preorder = [3,9,20,15,7] Middle order traversal inorder = [9,3,15,20,7] Return the following binary tree:

3 / \ 9 20 / \ 15 7

2, Problem solving ideas

For any tree, the form of preorder traversal is always [root node, [preorder traversal result of left subtree], [preorder traversal result of right subtree]] That is, the root node is always the first node in the preorder traversal.

The form of middle order traversal is always [[middle order traversal result of left subtree], root node, [middle order traversal result of right subtree]] As long as we locate the root node in the middle order traversal, we can know the number of nodes in the left subtree and the right subtree respectively. Since the lengths of preorder traversal and middle order traversal of the same subtree are obviously the same, we can locate all the left and right parentheses in the above form corresponding to the results of preorder traversal.

In this way, we know the pre order traversal and middle order traversal results of the left subtree and the pre order traversal and middle order traversal results of the right subtree. We can recursively construct the left subtree and the right subtree, and then connect the two subtrees to the left and right positions of the root node.

details

When locating the root node in the middle order traversal, a simple method is to directly scan the results of the whole middle order traversal and find the root node, but the time complexity is high. We can consider using a hash table to help us quickly locate the root node. For each key value pair in the hash map, the key represents an element (the value of the node), and the value represents its position in the middle order traversal. Before constructing the binary tree, we can scan the list traversed in the middle order to construct the hash map. In the process of constructing the binary tree, we only need O(1) to locate the root node.

3, Code

class Solution {
private:
    unordered_map<int, int> index;

public:
    TreeNode* myBuildTree(const vector<int>& preorder, const vector<int>& inorder, int preorder_left, int preorder_right, int inorder_left, int inorder_right) {
        if (preorder_left > preorder_right) {
            return nullptr;
        }
        
        // The first node in the preorder traversal is the root node
        int preorder_root = preorder_left;
        // Locate the root node in the middle order traversal
        int inorder_root = index[preorder[preorder_root]];
        
        // First establish the root node
        TreeNode* root = new TreeNode(preorder[preorder_root]);
        // Get the number of nodes in the left subtree
        int size_left_subtree = inorder_root - inorder_left;
        // The left subtree is constructed recursively and connected to the root node
        // The elements "size_left_subtree starting from the left boundary + 1" in the preorder traversal correspond to the elements "from the left boundary to the root node location - 1" in the inorder traversal
        root->left = myBuildTree(preorder, inorder, preorder_left + 1, preorder_left + size_left_subtree, inorder_left, inorder_root - 1);
        // The right subtree is constructed recursively and connected to the root node
        // The element "starting from the left boundary + 1 + number of left subtree nodes to the right boundary" in the preorder traversal corresponds to the element "locating from the root node + 1 to the right boundary" in the inorder traversal
        root->right = myBuildTree(preorder, inorder, preorder_left + size_left_subtree + 1, preorder_right, inorder_root + 1, inorder_right);
        return root;
    }

    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        int n = preorder.size();
        // Construct hash mapping to help us quickly locate the root node
        for (int i = 0; i < n; ++i) {
            index[inorder[i]] = i;
        }
        return myBuildTree(preorder, inorder, 0, n - 1, 0, n - 1);
    }
};

4, Complexity analysis

Time complexity: O(n), where n is the number of nodes in the tree.

Spatial complexity: O(n). In addition to the O(n) space required for the returned answer, we also need to use the space of O(n) to store hash mapping, and the space of O(h) (where h is the height of the tree) to represent the recursive time stack space. Here h < n, so the total space complexity is O(n).

Posted on Mon, 29 Nov 2021 02:44:53 -0500 by Mr. Tech