Serialize Deserialize Binary Tree
Encode a binary tree to a string and rebuild it — preorder with null markers or BFS level order.
advanced3 min read
- dsa
- tree
- interview
- Meta
The problem
Design an algorithm to serialize a binary tree to a string and deserialize that string back to the same tree structure and values.
1
/ \
2 3
/ \
4 5
// e.g. preorder: "1,2,#,#,3,4,#,#,5,#,#"
Any reversible format works. Interviewers care that nulls are represented so shape is unambiguous.
Node shape
class TreeNode {
val: number;
left: TreeNode | null;
right: TreeNode | null;
constructor(val = 0, left: TreeNode | null = null, right: TreeNode | null = null) {
this.val = val;
this.left = left;
this.right = right;
}
}
Brute-ish: JSON of nested objects
JSON.stringify a recursive object — works in JS but feels like cheating; also need a custom walk for interview signal.
Optimal: preorder + null sentinels
function serialize(root: TreeNode | null): string {
const parts: string[] = [];
function dfs(node: TreeNode | null): void {
if (!node) {
parts.push("#");
return;
}
parts.push(String(node.val));
dfs(node.left);
dfs(node.right);
}
dfs(root);
return parts.join(",");
}
function deserialize(data: string): TreeNode | null {
const parts = data.split(",");
let i = 0;
function dfs(): TreeNode | null {
const token = parts[i++];
if (token === "#" || token === undefined) return null;
const node = new TreeNode(Number(token));
node.left = dfs();
node.right = dfs();
return node;
}
return dfs();
}
BFS level-order variant
function serializeBfs(root: TreeNode | null): string {
if (!root) return "";
const q: (TreeNode | null)[] = [root];
const parts: string[] = [];
while (q.length) {
const node = q.shift()!;
if (!node) {
parts.push("#");
continue;
}
parts.push(String(node.val));
q.push(node.left, node.right);
}
return parts.join(",");
}
function deserializeBfs(data: string): TreeNode | null {
if (!data) return null;
const parts = data.split(",");
const root = new TreeNode(Number(parts[0]));
const q: TreeNode[] = [root];
let i = 1;
while (q.length && i < parts.length) {
const node = q.shift()!;
if (parts[i] !== "#") {
node.left = new TreeNode(Number(parts[i]));
q.push(node.left);
}
i++;
if (i < parts.length && parts[i] !== "#") {
node.right = new TreeNode(Number(parts[i]));
q.push(node.right);
}
i++;
}
return root;
}
| Time | O(n) serialize & deserialize |
| Space | O(n) string + recursion/queue |
Edge cases
- Empty tree
- Single node
- Negative values and multi-digit numbers — delimiter required
- Skewed tree — recursion depth
Common bugs
- Preorder without null markers → ambiguous trees
- Forgetting to advance index in deserialize
- Using
spliton empty string edge cases - Mixing BFS serialize with DFS deserialize
Interview delivery
- Need null markers.
- Pick preorder DFS or BFS.
- Implement both directions.
- Round-trip a small tree on the board.
- O(n).