We need to convert a binary tree into a string (serialize) and then reconstruct the exact same tree from that string (deserialize). The important word here is "exact." A tree with the same values is not enough; the structure has to match too. Left children must stay on the left, right children on the right, and null children must be preserved.
The difficulty comes from structure. Two different trees can produce the same inorder traversal of values, so a serialization that captures only values cannot tell them apart during deserialization. We need to encode the node values and where the nulls are, because null positions define the tree's shape.
Recording null markers (like "null" or "#") during traversal captures the complete structure. A preorder traversal with null markers uniquely defines a binary tree, and so does a level-order (BFS) traversal with null markers.
0 <= number of nodes <= 10^4: The tree can have up to 10,000 nodes. A skewed tree of this depth makes recursion depth a concern, which motivates the iterative BFS alternative.-1000 <= Node.val <= 1000: Node values can be negative. The parsing logic must treat a leading minus as part of the value, so "-1000" parses to the integer -1000 rather than a delimiter followed by "1000". Splitting on commas handles this, since the minus sign never appears as a delimiter.Preorder traversal (root, left, right) processes the root before either subtree. This ordering makes reconstruction direct: when we read the string back, the first token is always the current node, the tokens after it describe its left subtree, and whatever remains describes its right subtree.
Explicit null markers are what make this unambiguous. Without them, a node with only a left child and a node with only a right child would serialize identically. With them, the serialized string pins down both the values and the shape, so deserialization has exactly one valid interpretation.
The invariant that makes deserialization exact: a single recursive call consumes exactly the tokens that belong to its own subtree, no more and no fewer. A null marker is one token and one subtree (an empty one). A value token is followed by its full left subtree, then its full right subtree, both consumed by recursive calls before the call returns. Because every call leaves the index pointing at the first token of the next sibling subtree, the left call finishes precisely where the right call should begin.
Serialize:
Deserialize:
The DFS approach is O(n) in both time and space, which is optimal. Its one practical weakness is recursion depth: a skewed tree with 10,000 nodes causes 10,000 nested calls, which can overflow the call stack in languages with a small default stack. The next approach replaces the call stack with an explicit queue and serializes level by level instead of depth-first.
Instead of traversing depth-first, we serialize the tree level by level using BFS. This is the format LeetCode itself uses to represent binary trees in its input: [1,2,3,null,null,4,5].
A queue drives a level-by-level visit. For each node we dequeue, we append its value and enqueue both children. If a child is null, we append a null marker but enqueue nothing for it, since a null node has no children to expand.
Deserialization reverses this. The first token becomes the root and goes into a queue. For each node we dequeue, the next two tokens are its left and right children. A token of "N" means a null child; any other token becomes a new node that is attached and enqueued so its own children get assigned on a later iteration.
Because the work is driven by a queue rather than recursion, this version uses no call stack and handles deep trees without risk of stack overflow.
Serialize and deserialize agree because they enqueue nodes in the same order. During serialization, every non-null node appends exactly two tokens to the output (its left child and its right child). During deserialization, every non-null node we dequeue consumes exactly two tokens (its left child and its right child). Since both processes visit nodes in the same level-order sequence, the k-th non-null node produced during deserialization reads the same token pair that the k-th non-null node wrote during serialization. Null markers occupy a token but are never enqueued, so they never claim a child pair.
Serialize:
Deserialize: