297. Serialize and Deserialize Binary Tree
hardAsked at MicrosoftSerialize and Deserialize Binary Tree is Microsoft's litmus test for whether you can design a custom encoding and parse it back. The pre-order DFS with explicit null markers is the standard answer; the interviewer is grading whether your serializer and deserializer agree on exactly how nulls are represented.
By Sam K., Founder, InterviewChamp.AI · Last verified
Source citations
Public interview reports confirming this problem appears in Microsoft loops.
- Glassdoor (2026-Q1)— Microsoft Azure org senior onsite reports list Serialize/Deserialize as a 45-minute design-and-implement hard.
- Blind (2025-12)— Multiple Microsoft L62/L63 interview compilations include this question with the 'now make it compact' twist.
Problem
Serialization is the process of converting a data structure or object into a sequence of bits so that it can be stored in a file or memory buffer, or transmitted across a network connection link to be reconstructed later in the same or another computer environment. Design an algorithm to serialize and deserialize a binary tree. There is no restriction on how your serialization/deserialization algorithm should work. You just need to ensure that a binary tree can be serialized to a string and this string can be deserialized to the original tree structure.
Constraints
The number of nodes in the tree is in the range [0, 10^4].-1000 <= Node.val <= 1000
Examples
Example 1
root = [1,2,3,null,null,4,5][1,2,3,null,null,4,5]Example 2
root = [][]Approaches
1. Pre-order DFS with null markers (optimal)
Serialize: pre-order traversal, emit each value (or 'N' for null) separated by commas. Deserialize: split, then consume tokens one at a time recursively.
- Time
- O(n) each direction
- Space
- O(n) for the string + recursion
function serialize(root) {
const out = [];
function dfs(node) {
if (!node) { out.push('N'); return; }
out.push(String(node.val));
dfs(node.left);
dfs(node.right);
}
dfs(root);
return out.join(',');
}
function deserialize(data) {
const tokens = data.split(',');
let i = 0;
function build() {
if (tokens[i] === 'N') { i++; return null; }
const node = { val: Number(tokens[i++]), left: null, right: null };
node.left = build();
node.right = build();
return node;
}
return build();
}Tradeoff: Pre-order is the right traversal because the first token is always the root of the (sub)tree being built — the recursion can consume tokens linearly. In-order alone is insufficient because you can't tell where the left subtree ends without the structure.
2. Level-order BFS (LeetCode-style array)
BFS through the tree, emitting each node's value (or null marker). Deserialize by pairing children to parents level by level using a queue.
- Time
- O(n)
- Space
- O(n)
function serialize(root) {
if (!root) return '';
const out = [];
const queue = [root];
while (queue.length) {
const node = queue.shift();
if (!node) { out.push('N'); continue; }
out.push(String(node.val));
queue.push(node.left);
queue.push(node.right);
}
return out.join(',');
}
function deserialize(data) {
if (!data) return null;
const tokens = data.split(',');
const root = { val: Number(tokens[0]), left: null, right: null };
const queue = [root];
let i = 1;
while (queue.length && i < tokens.length) {
const node = queue.shift();
if (tokens[i] !== 'N') {
node.left = { val: Number(tokens[i]), left: null, right: null };
queue.push(node.left);
}
i++;
if (i < tokens.length && tokens[i] !== 'N') {
node.right = { val: Number(tokens[i]), left: null, right: null };
queue.push(node.right);
}
i++;
}
return root;
}Tradeoff: Matches LeetCode's display format, which is sometimes useful for debugging. Slightly trickier to parse because each iteration consumes exactly two tokens (left, right) per parent.
Microsoft-specific tips
Microsoft is grading the consistency between your serializer and deserializer. Before writing either, write the format spec out loud: 'I'm using comma-separated tokens; each value is the node's integer value; nulls are the literal string N; pre-order means root, left subtree, right subtree.' That spec is what holds the two halves together — they always either both work or both break the same way.
Common mistakes
- Using only in-order (or only post-order) without null markers — ambiguous structure.
- Using a delimiter that can appear in node values (e.g., '-' fails when values can be negative).
- In the BFS version, advancing the queue but forgetting to advance the index for the null branches.
Follow-up questions
An interviewer at Microsoft may pivot to one of these next:
- Serialize/Deserialize BST (LC 449) — exploit BST ordering to drop the null markers.
- Serialize/Deserialize N-ary Tree (LC 428).
- What if the values could be arbitrary strings? Quote them, escape delimiters.
Solve it now
Free. No sign-up. Python and JavaScript run instantly in your browser.
FAQ
Why pre-order and not in-order?
Pre-order writes the root first, so deserialize knows what to build at each step. With in-order and no structural markers, you can't tell where the left subtree ends.
Is the null marker really necessary?
Yes — without it, multiple distinct trees produce the same traversal output. The null marker is what makes the encoding lossless.
Free learning resources
Curated free links for this problem.