#297 Serialize and Deserialize Binary Tree
frequently reported atLinkedInMicrosoftByteDance / TikTokUberAmazonNVIDIA
the problem
In plain words
Design a Codec with serialize(root) → String and deserialize(data) → root, such that deserialize(serialize(tree)) rebuilds the same tree. One Codec object may write and a different one read. The format is up to you.
in root = [1,2,3,null,null,4,5]
out [1,2,3,null,null,4,5]
Any string format works as long as the round trip is exact.
in root = []
out []
- 0 ≤ number of nodes ≤ 10⁴
- -1000 ≤ Node.val ≤ 1000
your turn
Try it before you peek
Read the examples, say the brute force out loud, then write code: here or on LeetCode ↗. Stuck for 20 minutes? Open one hint at a time.
Solve it in the browser
Design: implement every operation. Compiled by the real javac (Java 17) and judged right here — nothing is sent anywhere.
Solutions are hidden so you can try first. Even 20 minutes of real effort makes the answer stick far better than reading it.
Marking the problem solved, or opening every hint, also shows it.
the aha
Key insight
patternBuild a tree from traversalsTree BFS (level order)
where this runsLeetCode's own tree notation, like [1,null,2], is level order with null markers — the BFS codec on this page.
One traversal is ambiguous — unless you also write down the nulls. With null markers, a preorder string pins the tree down exactly, and the reader rebuilds it in the same order it was written.
solutions
From brute force to optimal
Write nodes level by level, "#" for a missing child; read them back two at a time per parent.
- BFS that also queues nulls (LinkedList) and writes "#".
- Deserialize: queue of parents; each parent consumes the next two tokens as its children.
Each node and null marker is written and read once.
The string, the token array and the queue — and no recursion, so deep trees are safe.
class Codec { /** Level order, "#" for a missing child: "1,2,3,#,#,4,5,#,#,#,#". */ public String serialize(TreeNode root) { if (root == null) return ""; StringBuilder sb = new StringBuilder(); Queue<TreeNode> queue = new LinkedList<>(); // LinkedList allows null; ArrayDeque does not queue.offer(root); while (!queue.isEmpty()) { TreeNode node = queue.poll(); if (node == null) { sb.append("#,"); continue; } sb.append(node.val).append(','); queue.offer(node.left); queue.offer(node.right); } return sb.toString(); } public TreeNode deserialize(String data) { if (data.isEmpty()) return null; String[] tokens = data.split(","); TreeNode root = new TreeNode(Integer.parseInt(tokens[0])); Deque<TreeNode> parents = new ArrayDeque<>(); parents.offer(root); int i = 1; while (!parents.isEmpty()) { // tokens come in pairs: left child, right child TreeNode parent = parents.poll(); if (!tokens[i].equals("#")) { parent.left = new TreeNode(Integer.parseInt(tokens[i])); parents.offer(parent.left); } i++; if (!tokens[i].equals("#")) { parent.right = new TreeNode(Integer.parseInt(tokens[i])); parents.offer(parent.right); } i++; } return root; }}Write root, left, right recursively with "#" for null; read tokens back in the same order.
- serialize: null → "#,"; else value, then left, then right.
- deserialize: poll a token; "#" → null; else make a node, build its left, then its right.
Each node and each of the n + 1 nulls is handled once.
The string and token deque; the recursion is O(h).
class Codec { /** Preorder, "#" for null: "1,2,#,#,3,4,#,#,5,#,#". */ public String serialize(TreeNode root) { StringBuilder sb = new StringBuilder(); write(root, sb); return sb.toString(); } private void write(TreeNode node, StringBuilder sb) { if (node == null) { sb.append("#,"); return; } sb.append(node.val).append(','); write(node.left, sb); write(node.right, sb); } public TreeNode deserialize(String data) { Deque<String> tokens = new ArrayDeque<>(Arrays.asList(data.split(","))); return read(tokens); } /** Consumes exactly one subtree's worth of tokens, in the same order they were written. */ private TreeNode read(Deque<String> tokens) { String token = tokens.poll(); if (token.equals("#")) return null; TreeNode node = new TreeNode(Integer.parseInt(token)); node.left = read(tokens); node.right = read(tokens); return node; }}Dry run
in the room
How to say it in the interview
talk track
- State the format first and show it on the example tree: "1,2,#,#,3,4,#,#,5,#,#,".
- Explain why null markers make one traversal enough.
- Mention the recursion-depth risk for skewed trees and that the BFS codec avoids it.
traps
- Forgetting separators: 1 and 23 vs 12 and 3.
- Using
ArrayDequeto queue null children — it throws. - Building a String with
+=in a loop: O(n²). UseStringBuilder. - Keeping the tree in a field instead of really encoding it — a different Codec object does the reading.
what they ask next
Follow-ups
Serialize and Deserialize BST (LC 449)?
Preorder without null markers is enough: the BST ordering tells you where each value goes (rebuild with value bounds).
Make it compact?
Write values as fixed-width binary (4 bytes each) plus a bitmap for nulls instead of text.
before you submit
Edge cases to test
- Empty tree → serialize to a marker, and deserialize it back to null.
- Negative and multi-digit values: "-1000," must not merge with its neighbours.
- A deep chain: the recursive codec is as deep as the tree — the BFS codec has no recursion at all.
practise next
Similar problems
- #105Construct Binary Tree from Preorder and Inorder TraversalMediumin Tree Recursion
- #102Binary Tree Level Order TraversalMediumin Traversals
- #100Same TreeEasyin Tree Recursion