Serialize and deserialize a binary tree

Serialization is to store a tree in an array so that it can be later restored and deserialization is reading tree back from the array. Complete the functions

  • serialize() : stores the tree into an array a and returns the array.
  • deSerialize() : deserializes the array to the tree and returns the root of the tree.

Note: Multiple nodes can have the same data and the node values are always positive integers. Your code will be correct if the tree returned by deSerialize(serialize(input_tree)) is same as the input tree. Driver code will print the in-order traversal of the tree returned by deSerialize(serialize(input_tree)).

Examples :

Input: root = [1, 2, 3]
      
Output: [2, 1, 3]
Input: root = [10, 20, 30, 40, 60, N, N]
      
Output: [40, 20, 60, 10, 30]

Constraints:
1 <= Number of nodes <= 104
1 <= Data of a node <= 109


Approach 01:

#include <queue>
#include <vector>

class Solution {
  public:
    // Helper function for inorder traversal during serialization
    void inorderTraversal(Node* root, vector<int>& serializedTree) {
        if (root == nullptr) return;
        inorderTraversal(root->left, serializedTree);
        serializedTree.push_back(root->data);
        inorderTraversal(root->right, serializedTree);
    }

    // Serialize the binary tree into a vector using inorder traversal
    vector<int> serialize(Node *root) {
        vector<int> serializedTree;
        inorderTraversal(root, serializedTree);
        return serializedTree;
    }

    // Helper function to recursively construct the tree during deserialization
    void constructTree(vector<int>& serializedTree, int index, Node* root, Node*& resultTree) {
        if (index >= serializedTree.size()) return;

        Node* currentNode = new Node(serializedTree[index]);
        currentNode->left = root;

        if (index + 1 < serializedTree.size()) {
            Node* rightNode = new Node(serializedTree[index + 1]);
            currentNode->right = rightNode;
        }

        resultTree = currentNode;
        constructTree(serializedTree, index + 2, currentNode, resultTree);
    }

    // Deserialize the vector into a binary tree
    Node* deSerialize(vector<int>& serializedTree) {
        Node* root = new Node(serializedTree[0]);
        if (serializedTree.size() == 1) {
            return root;
        }

        Node* resultTree = nullptr;
        constructTree(serializedTree, 1, root, resultTree);
        return resultTree;
    }
};
class Solution:
    
    def inorderTraversal(self, root, serializedTree):
        if not root:
            return
        self.inorderTraversal(root.left, serializedTree)
        serializedTree.append(root.data)
        self.inorderTraversal(root.right, serializedTree)

    def serialize(self, root):
        serializedTree = []
        self.inorderTraversal(root, serializedTree)
        return serializedTree

    def constructTree(self, serializedTree, index, root, resultTree):
        if index >= len(serializedTree):
            return
        
        currentNode = Node(serializedTree[index])
        currentNode.left = root

        if index + 1 < len(serializedTree):
            rightNode = Node(serializedTree[index + 1])
            currentNode.right = rightNode

        resultTree[0] = currentNode
        self.constructTree(serializedTree, index + 2, currentNode, resultTree)

    def deSerialize(self, serializedTree):
        root = Node(serializedTree[0])
        if len(serializedTree) == 1:
            return root
        
        resultTree = [None]
        self.constructTree(serializedTree, 1, root, resultTree)
        return resultTree[0]

Time Complexity:

  • Serialization:

    The serialize function performs an inorder traversal of the binary tree, which takes \( O(n) \) time.

  • Deserialization:

    The deSerialize function reconstructs the tree using a recursive approach, which also takes \( O(n) \) time.

  • Total Time Complexity:

    Since both serialization and deserialization run in \( O(n) \) time, the overall time complexity is \( O(n) \).

Space Complexity:

  • Serialization Storage:

    The serialized tree is stored in a vector of size \( O(n) \).

  • Recursive Stack:

    The recursion depth in the worst case (a skewed tree) is \( O(n) \).

  • Total Space Complexity:

    The total space complexity is \( O(n) \) due to both the vector storage and recursion stack.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top