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 Alex Chen, 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.
Practice these live with InterviewChamp.AI
Drill Serialize and Deserialize Binary Tree and other Microsoft interview questions under real-loop conditions with instant feedback on your reasoning, complexity claims, and code.
Practice these live with InterviewChamp.AI →