Programming & Development / April 10, 2025

LeetCode 297: Serialize and Deserialize Binary Tree – Efficient Tree Serialization and Deserialization

LeetCode 297 Serialize and Deserialize Binary Tree tree traversal binary tree serialization deserialization preorder traversal BFS queue binary tree encoding binary tree decoding Python tree data structure

Introduction

LeetCode 297: Serialize and Deserialize Binary Tree is a problem where you are asked to implement two functions:

  1. serialize(root): Convert a binary tree into a string representation.
  2. deserialize(data): Convert a string representation back into the binary tree.

This problem tests your understanding of tree traversal and encoding/decoding techniques. A common approach is to use preorder traversal (or level-order traversal) to serialize the tree and reverse the process to deserialize it.

Problem Statement

You need to design an algorithm that supports two operations for a binary tree:
  1. Serialize: Convert the binary tree into a string format that can be easily stored or transmitted.
  2. Deserialize: Convert the string back into the original binary tree.

The encoding and decoding should be done in such a way that the original tree structure can be recovered from the serialized data.

Example

python

# Example 1:

Input:
["Codec", "serialize", "deserialize"]
[[], [root], [serialized_tree]]

Output:
[null, "[1,2,3,null,null,4,5]", root]

Explanation:

  • serialize(root) returns a string representation of the binary tree.
  • deserialize(serialized_tree) reconstructs the tree from the string and returns the root of the tree.

βœ… Step-by-Step Solution

🧠 Intuition

To solve this problem, we need to find a way to efficiently:

  1. Serialize the tree structure into a string (for example, using a preorder traversal).
  2. Deserialize the string back into the original tree.

For this task, we can use preorder traversal or level-order traversal:

  • Preorder Traversal involves visiting the root node first, then recursively the left and right subtrees.
  • During Serialization, we can represent each node's value as part of a string. For null nodes, we can use a placeholder like None or "null".
  • Deserialization involves converting the string back into a tree by processing each node in the order they appear in the serialized data.

βœ… Approach

  1. Serialize:
  • Use preorder traversal (root -> left -> right) to visit nodes.
  • For each node, append its value to the string.
  • Use a placeholder ("null") to represent empty child nodes.
  1. Deserialize:
  • Convert the serialized string back into a list of values.
  • Recursively rebuild the tree by following the preorder traversal sequence.
  1. Edge Case:
  • If the tree is empty (i.e., root is None), the serialized string should be empty or contain a special value.

βœ… Python Code

python

class Codec:
    
    def serialize(self, root):
        """Encodes a tree to a single string."""
        def preorder(node):
            if not node:
                return "null"
            # Preorder traversal: root -> left -> right
            return str(node.val) + "," + preorder(node.left) + "," + preorder(node.right)
        
        return preorder(root)
    
    def deserialize(self, data):
        """Decodes your encoded data to tree."""
        def build_tree(data_list):
            # Base case: if the data_list is empty or the current value is "null"
            if not data_list:
                return None
            value = data_list.pop(0)
            if value == "null":
                return None
            node = TreeNode(int(value))  # create a new tree node
            node.left = build_tree(data_list)  # recursively build left subtree
            node.right = build_tree(data_list)  # recursively build right subtree
            return node
        
        # Convert the serialized string to a list and start deserialization
        data_list = data.split(',')
        return build_tree(data_list)

# Definition for a binary tree node.
class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

πŸ§ͺ How It Works

  1. Serialization (serialize):
  • We define a recursive function preorder(node) which performs a preorder traversal. This traversal visits the root first, followed by the left subtree, and then the right subtree.
  • For each node:
  • If the node is None (empty), append "null" to the string.
  • Otherwise, append the node’s value, followed by the serialized left and right subtrees.
  • This approach ensures that all nodes, including null nodes, are represented in the final serialized string.
  1. Deserialization (deserialize):
  • The deserialize function splits the serialized string into a list of values.
  • We then recursively rebuild the tree by popping values from the list:
  • If the value is "null", it means the node is absent (empty).
  • Otherwise, a new TreeNode is created with the value, and the left and right subtrees are recursively built from the list.

⏱️ Time and Space Complexity

MetricValueTime Complexity (serialize)O(n), where n is the number of nodes in the tree. We visit each node once during the preorder traversal.Time Complexity (deserialize)O(n), where n is the number of nodes in the tree. We process each value once during the deserialization.Space ComplexityO(n), where n is the number of nodes in the tree. The space complexity comes from the recursion stack and the storage required for the serialized string.

  • Time Complexity for serialize(root): We perform a preorder traversal of the tree, visiting each node once. Therefore, the time complexity is O(n), where n is the number of nodes.
  • Time Complexity for deserialize(data): We split the string into a list and then rebuild the tree by processing each value once. The time complexity is O(n), where n is the number of nodes.
  • Space Complexity: Both the recursion stack and the string storage require space proportional to the number of nodes in the tree, so the space complexity is O(n).

πŸ” Edge Cases

  1. Empty Tree:
  • If the tree is empty, root is None. The serialized string should be empty or contain a special marker like "null".
  • When deserializing, an empty or special marker string should result in a None tree.
  1. Single Node:
  • For a tree with only one node, the serialized string should contain the node value and two "null" markers for the left and right children.
  1. Unbalanced Tree:
  • The algorithm works for both balanced and unbalanced trees. The recursive nature of both the serialization and deserialization handles various tree shapes correctly.
  1. Multiple Levels:
  • The solution works efficiently for trees with multiple levels. The recursion handles both deep and shallow trees without any issues.

βœ… Conclusion

LeetCode 297: Serialize and Deserialize Binary Tree is a problem that involves converting a binary tree into a string format and vice versa. Using preorder traversal for serialization and recursion for deserialization, we can effectively encode and decode the tree while maintaining the original structure.

By leveraging recursive tree traversal and careful management of node values, this solution ensures that both serialization and deserialization are done efficiently with a time complexity of O(n).


Comments

No comments yet

Add a new Comment

NUHMAN.COM

Information Technology website for Programming & Development, Web Design & UX/UI, Startups & Innovation, Gadgets & Consumer Tech, Cloud Computing & Enterprise Tech, Cybersecurity, Artificial Intelligence (AI) & Machine Learning (ML), Gaming Technology, Mobile Development, Tech News & Trends, Open Source & Linux, Data Science & Analytics

Categories

Tags

©{" "} Nuhmans.com . All Rights Reserved. Designed by{" "} HTML Codex