Serialize and Deserialize Binary Tree in DSA C++ - Time & Space Complexity
We want to understand how long it takes to convert a binary tree into a string and back.
How does the time needed grow as the tree gets bigger?
Analyze the time complexity of the following code snippet.
void serialize(TreeNode* root, ostringstream &out) {
if (!root) {
out << "# ";
return;
}
out << root->val << ' ';
serialize(root->left, out);
serialize(root->right, out);
}
TreeNode* deserialize(istringstream &in) {
string val;
in >> val;
if (val == "#") return nullptr;
TreeNode* node = new TreeNode(stoi(val));
node->left = deserialize(in);
node->right = deserialize(in);
return node;
}
This code converts a binary tree to a string and back using preorder traversal with markers for null nodes.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Recursive traversal of each node in the tree.
- How many times: Each node is visited exactly once during serialization and once during deserialization.
As the number of nodes in the tree grows, the time to serialize and deserialize grows proportionally.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 visits plus null markers |
| 100 | About 100 visits plus null markers |
| 1000 | About 1000 visits plus null markers |
Pattern observation: The operations grow linearly with the number of nodes.
Time Complexity: O(n)
This means the time to serialize or deserialize grows directly with the number of nodes in the tree.
[X] Wrong: "Serialization takes constant time because it just converts to a string."
[OK] Correct: The code must visit every node to record its value or null marker, so time grows with tree size.
Understanding this helps you explain how tree data can be saved and restored efficiently, a common real-world need.
"What if we used level-order traversal instead of preorder? How would the time complexity change?"
Practice
serialize and deserialize functions in the context of a binary tree?Solution
Step 1: Understand serialization
Serialization means converting a data structure like a binary tree into a string format that can be stored or transmitted.Step 2: Understand deserialization
Deserialization means converting the string back into the original binary tree structure.Final Answer:
Convert a binary tree to a string and back to a binary tree -> Option DQuick Check:
Serialize/Deserialize = Convert tree to/from string [OK]
- Confusing serialization with sorting
- Thinking it deletes nodes
- Assuming it calculates tree height
Solution
Step 1: Identify common null markers
In many serialization methods, a special character like '#' is used to mark null nodes to distinguish them from valid node values.Step 2: Compare options
"null" is a string but longer and less common; 0 and -1 can be valid node values, so they are ambiguous.Final Answer:
"#" -> Option BQuick Check:
Null node marker = "#" [OK]
- Using 0 or -1 which can be valid node values
- Using the word "null" which is verbose
- Not marking null nodes at all
"1 2 # # 3 4 # # 5 # #", what is the inorder traversal of the tree?Solution
Step 1: Reconstruct the tree from preorder
Preorder: 1 (root), 2 (left child), # (left null), # (right null), 3 (right child), 4 (left child), #, #, 5 (right child), #, #.Step 2: Draw the tree and find inorder
Tree structure:
1
/ \
2 3
/ \
4 5
Inorder (left, root, right): 2 1 4 3 5Final Answer:
2 1 4 3 5 -> Option AQuick Check:
Inorder from tree = 2 1 4 3 5 [OK]
- Mixing preorder and inorder sequences
- Ignoring null markers
- Incorrect tree reconstruction
TreeNode* deserializeHelper(vector<string>& data, int& index) {
if (index >= data.size() || data[index] == "#") {
index++;
return nullptr;
}
TreeNode* node = new TreeNode(stoi(data[index++]));
node->left = deserializeHelper(data, index);
node->right = deserializeHelper(data, index);
return node;
}
What is the bug in this code?Solution
Step 1: Identify the stoi vulnerability
The code usesstoi(data[index++])without validating thatdata[index]is a valid integer string. Malformed input (non-numeric other than '#') causes unhandledstd::invalid_argumentexception.Step 2: Rule out other options
Index increments once per token: for '#' viaindex++in if; for values viaindex++in stoi. Empty input handled byindex >= data.size(). Right child assigned correctly.Final Answer:
The stoi conversion can throw exception without try-catch -> Option AQuick Check:
stoi requires valid numeric strings [OK]
- Assuming no index increment for null nodes
- Ignoring possible exceptions from stoi
- Thinking right child assignment is missing
Solution
Step 1: Consider node values including negatives and zero
Using space-separated values with '#' for nulls preserves structure and allows negative values as strings can represent negatives.Step 2: Evaluate other options
Use comma-separated values but skip null markers to reduce size skips nulls, losing tree shape.
Serialize only node values ignoring nulls, reconstruct tree by sorting ignores nulls and sorts, losing original structure.
Serialize using preorder but replace negative values with zero replaces negatives with zero, losing data.Final Answer:
Use space-separated values with '#' for nulls and convert strings to int using stoi -> Option CQuick Check:
Preserve nulls and convert strings properly [OK]
- Skipping null markers losing tree shape
- Replacing negative values losing data
- Sorting nodes losing original tree
Ready to prove it?
Pass the test and this pattern moves unknown
