◀ THE GRIND — TREES

Serialize And Deserialize Binary Tree

The drill: Turn a binary tree into one string and turn that string back into the exact same tree — same shape, same null placement, same values — with no shared object between the two sides, only the text.

THE BRIEFING — THE FULL DRILL, IN MY OWN WORDS

A binary tree needs to become a single string and then turn back into a tree from nothing but that string — no shared references between the writing side and the reading side, only the text passes between them.

The rebuilt tree has to match the original exactly: same shape, same values, same nulls in the same places, since a wrong reconstruction can't be told apart from a right one without checking every branch.

This site checks the drill as one round trip — your function takes a tree, encodes and decodes it internally however you like, and the judge compares the tree that comes back out against the one that went in.

EX 01
root = [7]
[7]
SINGLE NODE
EX 02
root = []
[]
EMPTY TREE
EX 03
root = [0]
[0]
SINGLE NODE VALUED ZERO
THE HINTS — TAKE ONLY WHAT YOU NEED
HINT 1 THE NUDGE

A tree can't cross a wire as pointers — it has to flatten into a sequence of tokens first, and that sequence has to carry enough information to rebuild every branch, including the ones that don't exist.

HINT 2 THE STRUCTURE

A fixed traversal order plus an explicit marker for “no child here” is enough — the reader just needs to know, at every step, whether the next token opens a subtree or closes one early.

HINT 3 ONE STEP FROM THE ANSWER

Preorder: write the value, then recurse left, then right, writing a marker in place of every null. Decoding replays the same order — pull one token at a time and it tells you whether to build a node or stop.

COACH'S BOARD — THE PATTERN, STEP BY STEP
MARKERS FOR NOTHINGPATTERN · PREORDER WITH MARKERSroot = [5, 3, 8]
QUEUE
— empty —
STEP 1

Serialize with preorder: write a node's value, then recurse left, then right — write # for every missing child so nulls survive the trip.

STEP 1 / 7 · ← → WORK TOO
THE SPLITS — TWO PACES, TWO LANGUAGES
grind/serialize-and-deserialize-binary-tree.pyRACE PACE
LANG ▸
PACE ▸
class Codec:
    def serialize(self, root: Optional[TreeNode]) -> str:
        vals = []

        def dfs(node):
            if node is None:
                vals.append("#")
                return
            vals.append(str(node.val))
            dfs(node.left)
            dfs(node.right)

        dfs(root)
        return ",".join(vals)

    def deserialize(self, data: str) -> Optional[TreeNode]:
        tokens = iter(data.split(","))

        def build():
            val = next(tokens)
            if val == "#":
                return None
            node = TreeNode(int(val))
            node.left = build()
            node.right = build()
            return node

        return build()


class Solution:
    def roundTrip(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
        codec = Codec()
        return codec.deserialize(codec.serialize(root))
TIME O(N)SPACE O(N)PYTHON · RACE PACE · 34 LN

✓ CHIP-TIMED — ALL 4 SOLUTIONS RAN GREEN AGAINST SELF-AUTHORED CASES IN CI · JDK 21 · CPYTHON 3.12 · NOTHING PUBLISHES RED