Fatskills
Practice. Master. Repeat.
Study Guide: How to Solve: Serialize and Deserialize a Binary Tree
Source: https://www.fatskills.com/leetcode/chapter/how-to-solve-serialize-and-deserialize-a-binary-tree

How to Solve: Serialize and Deserialize a Binary Tree

By Fatskills Exam Guides Team — the exam nerds behind 28,500+ quizzes and 2.1M practice questions across 500+ global exams.

⏱️ ~7 min read

How to Solve: Serialize and Deserialize a Binary Tree

(A Complete FAANG-Level Interview Guide)


? Introduction

"This problem appears in 1 out of every 3 onsite interviews—master it, and you prove you can handle recursion, tree traversals, and string parsing under pressure, a trifecta FAANG interviewers love to test."


? WHAT YOU NEED TO KNOW FIRST

Before diving in, ensure you understand: 1. Binary Tree Traversals (DFS: Pre/In/Post-order, BFS: Level-order)
- Why? Serialization/deserialization relies on traversing the tree in a consistent order. 2. Recursion & Backtracking
- Why? Trees are recursive structures; recursion simplifies traversal logic. 3. String Parsing (Splitting, Joining, Handling Delimiters)
- Why? Serialization converts trees to strings; deserialization parses strings back into trees.


? KEY TECHNIQUES & PATTERNS

Technique / Pattern When to Use Quick Example
Pre-order DFS Serializing/deserializing with recursion serialize(root): [root.val, serialize(left), serialize(right)]
Level-order BFS Serializing/deserializing iteratively serialize(root): [root.val, left.val, right.val, left.left.val, ...]
Delimiter-Based Parsing Handling null nodes in strings Use "#" for null; split string by "," during deserialization.
Queue for BFS Reconstructing trees level by level deserialize(data): queue = [root]; while queue: node = queue.pop(); ...
Recursive Deserialization Rebuilding trees from pre-order strings deserialize(data): val = data.pop(); if val == "#": return null; ...
StringBuilder (Java) / Join (Python) Efficient string concatenation ",".join([str(x) for x in nodes]) (Python) or StringBuilder (Java).

? STEP-BY-STEP FRAMEWORK

(Repeatable mental checklist for any serialization/deserialization problem.)

  1. Choose a Traversal Order
  2. Decide: Pre-order DFS (recursive, simpler) or Level-order BFS (iterative, handles large trees better).
  3. Rule of thumb: Pre-order is easier to implement; BFS is more intuitive for level-wise reconstruction.

  4. Define the Serialization Format

  5. Pick a delimiter (e.g., ",") to separate node values.
  6. Pick a marker for null nodes (e.g., "#" or "null").
  7. Example: [1,2,#,#,3,4,#,#,5,#,#] (pre-order).

  8. Serialize the Tree

  9. Traverse the tree in your chosen order.
  10. Append node values to a list (or string) during traversal.
  11. Replace null nodes with your marker.
  12. Join the list into a string with delimiters.

  13. Deserialize the String

  14. Split the string into a list of tokens using your delimiter.
  15. Reconstruct the tree by:

    • Pre-order: Recursively build left/right subtrees.
    • Level-order: Use a queue to assign children level by level.
  16. Edge Cases & Validation

  17. Handle empty trees (root == null).
  18. Validate the serialized string (e.g., check for balanced null markers).
  19. Test with skewed trees (e.g., left-heavy or right-heavy).

  20. Optimize for Time/Space

  21. Time: O(N) for both serialization and deserialization (visit each node once).
  22. Space: O(N) for the output string and recursion stack (DFS) or queue (BFS).

? WORKED EXAMPLES

Example 1: Basic (Pre-order DFS)

Problem: Serialize and deserialize a binary tree using pre-order traversal.

Thought Process

  1. Traversal Order: Pre-order (root → left → right).
  2. Serialization:
  3. If node is null, return "#".
  4. Else, return str(node.val) + "," + serialize(left) + "," + serialize(right).
  5. Deserialization:
  6. Split the string into tokens.
  7. Recursively build the tree: first token is root, then left subtree, then right subtree.

Code (Python)

class TreeNode:

def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right class Codec:
def serialize(self, root):
"""Encodes a tree to a single string."""
def helper(node):
if not node:
return "#"
return str(node.val) + "," + helper(node.left) + "," + helper(node.right)
return helper(root)
def deserialize(self, data):
"""Decodes your encoded data to tree."""
def helper(nodes):
val = next(nodes)
if val == "#":
return None
node = TreeNode(int(val))
node.left = helper(nodes)
node.right = helper(nodes)
return node
# Split data into tokens and convert to iterator
nodes = iter(data.split(","))
return helper(nodes)

Complexity

  • Time: O(N) for both serialization and deserialization (each node visited once).
  • Space: O(N) for the output string and recursion stack.

Why This Works

  • Pre-order traversal ensures the root is always the first element, making reconstruction straightforward.
  • Recursion naturally handles the tree’s recursive structure.

Example 2: Medium (Level-order BFS)

Problem: Serialize and deserialize a binary tree using level-order traversal.

Thought Process

  1. Traversal Order: Level-order (BFS).
  2. Serialization:
  3. Use a queue to traverse the tree level by level.
  4. Append node values to a list; use "#" for null.
  5. Deserialization:
  6. Split the string into tokens.
  7. Use a queue to reconstruct the tree level by level.

Code (Python)

from collections import deque

class Codec:

def serialize(self, root):
"""Encodes a tree to a single string."""
if not root:
return ""
queue = deque([root])
res = []
while queue:
node = queue.popleft()
if node:
res.append(str(node.val))
queue.append(node.left)
queue.append(node.right)
else:
res.append("#")
return ",".join(res)
def deserialize(self, data):
"""Decodes your encoded data to tree."""
if not data:
return None
nodes = data.split(",")
root = TreeNode(int(nodes[0]))
queue = deque([root])
i = 1
while queue and i < len(nodes):
node = queue.popleft()
if nodes[i] != "#":
node.left = TreeNode(int(nodes[i]))
queue.append(node.left)
i += 1
if i < len(nodes) and nodes[i] != "#":
node.right = TreeNode(int(nodes[i]))
queue.append(node.right)
i += 1
return root

Complexity

  • Time: O(N) for both serialization and deserialization.
  • Space: O(N) for the queue and output string.

Why This Works

  • BFS ensures nodes are processed level by level, making reconstruction intuitive.
  • The queue tracks nodes whose children need to be assigned.

Example 3: Hard (Follow-up - Compact Serialization)

Problem: Serialize the tree in a compact format (e.g., omit trailing null markers).

Thought Process

  1. Traversal Order: Pre-order (simpler for compactness).
  2. Serialization:
  3. Only include null markers for leaves (not for internal nodes with one child).
  4. Example: [1,2,#,#,3,4,#,#,5] (instead of [1,2,#,#,3,4,#,#,5,#,#]).
  5. Deserialization:
  6. Use a recursive helper that tracks the current index in the token list.
  7. Stop when all tokens are consumed.

Code (Python)

class Codec:

def serialize(self, root):
"""Encodes a tree to a compact string."""
def helper(node):
if not node:
return []
res = [str(node.val)]
if not node.left and not node.right:
return res
res += helper(node.left)
res += helper(node.right)
return res
return ",".join(helper(root))
def deserialize(self, data):
"""Decodes a compact string to tree."""
if not data:
return None
tokens = data.split(",")
def helper():
if not tokens:
return None
val = tokens.pop(0)
node = TreeNode(int(val))
if tokens and tokens[0] != "#":
node.left = helper()
if tokens and tokens[0] != "#":
node.right = helper()
return node
return helper()

Complexity

  • Time: O(N) for both serialization and deserialization.
  • Space: O(N) for the output string and recursion stack.

Why This Works

  • Compact serialization reduces string size by omitting redundant null markers.
  • Deserialization uses the same pre-order logic but stops early for leaves.

❌ Common Mistakes

Mistake Why It Happens Correct Approach
Not handling null nodes Forgetting to mark null in serialization. Always include a marker (e.g., "#") for null nodes.
Incorrect delimiter choice Using a delimiter that appears in node values (e.g., "," in strings). Pick a delimiter not present in node values (e.g., "|" or " " for strings).
Off-by-one errors in deserialization Mismanaging indices when splitting tokens. Use an iterator (Python) or track indices carefully (Java/C++).
Stack overflow in recursion Deep recursion for large trees. Use BFS (iterative) for very large trees to avoid stack overflow.
Not testing edge cases Forgetting empty trees or skewed trees. Test with: empty tree, single-node tree, left-skewed tree, right-skewed tree.

?️ INTERVIEW TrapS

Trap How to Spot It How to Avoid It
"What if node values are strings?" Interviewer asks about non-integer values. Use a delimiter not present in node values (e.g., "|" for strings).
"Can you do it iteratively?" Follow-up after recursive solution. Implement BFS (level-order) using a queue for iterative serialization/deserialization.
"Optimize for space." Follow-up after basic solution. Use compact serialization (omit trailing null markers) or binary encoding.

? 1-Minute Recap

"Alright, let’s lock this in. Here’s your 60-second recap:

  1. Pick a traversal: Pre-order (recursive) or level-order (iterative). Pre-order is simpler; BFS is better for large trees.
  2. Serialize: Traverse the tree, append node values to a string, and mark null nodes with a delimiter (e.g., "#").
  3. Deserialize: Split the string, then rebuild the tree using the same traversal order. For pre-order, use recursion; for BFS, use a queue.
  4. Edge cases: Test empty trees, skewed trees, and non-integer values.
  5. Follow-ups: Be ready for compact serialization, iterative solutions, or handling strings.

Remember: The key is consistency. Whatever order you serialize in, you must deserialize in the same order. Nail this, and you’ve just aced a problem that trips up 50% of candidates. Now go crush that interview!"


? Final Notes

  • Practice: Implement both DFS and BFS versions. Time yourself (aim for <15 mins per solution).
  • Whiteboard: Draw the tree and serialization string side by side to visualize the process.
  • Follow-ups: Prepare for:
  • Compact serialization (omit trailing null markers).
  • Iterative solutions (BFS or stack-based DFS).
  • Handling non-integer node values (e.g., strings).


ADVERTISEMENT