Build and Serialize
What is this?
So far we've been reading trees โ here we make them. That means building a new tree, drawing one out as a picture, or flattening one into a line of text so it can be saved or sent and then rebuilt later, exactly. It's like writing down assembly instructions for a piece of furniture so detailed that someone on the other side of the world can recreate it piece for piece. The secret is choosing an order to record things in that leaves zero ambiguity.
๐ก Fun fact: Turning a tree into a string is called "serialization," the same idea that lets your browser save a web page or a game save your progress to disk. The make-or-break detail is recording the empty spots too โ without those blank markers, many different trees would flatten to the same text and could never be told apart.
๐ The 3 problems in this chapter are free. Sign in with Google or Microsoft to start solving.
Core idea: These problems are about producing a tree or a representation of one, rather than just reading it. The unifying move is a recursive walk where structure drives the work: visit nodes in a fixed order, and let each node's position in the recursion tell you what to create, where to place it, or what to write down. Get the order and the position right, and building mirrors traversing.
The pattern
Construction is traversal run in reverse. When you read a tree you consume its nodes in some order; when you build or encode one, you emit or place nodes in that same order. The trick is choosing an order that is unambiguous โ that lets you (or a later reader) recover exactly one tree.
Two reliable orders show up here. Parallel DFS walks two trees at once, pairing up nodes by identical position so you can combine them. Position-by-formula uses the fact that in a perfect binary tree a node's row and column are computable from its depth, so you can drop nodes into a grid without any extra bookkeeping. And for full round-tripping, preorder with explicit null markers records enough about the shape that decoding becomes a straightforward replay.
The problems
- Merge Two Binary Trees โ parallel DFS: recurse on both trees together; where both have a node, sum them; where only one does, splice that subtree in wholesale.
- Print Binary Tree โ compute the output grid's height and width from the tree's depth, then place each node at the column its position formula dictates so the layout reads like a real tree.
- Serialize and Deserialize Binary Tree โ preorder DFS writing values plus null placeholders, so the marker stream encodes the shape; deserialize replays that stream in the same preorder to rebuild it.
Key takeaways
- Building is traversal in reverse โ pick a node order that uniquely determines the tree, then emit or place in that order.
- Parallel DFS handles any "combine two trees by position" task in one pass.
- Null markers are what make a flat string round-trip โ they carry the structure that values alone would lose.
- Why interviewers like it: serialization forces you to reason about what information uniquely identifies a tree, a deeper test than a plain traversal.
Order: Merge Two Binary Trees โ Print Binary Tree โ Serialize and Deserialize Binary Tree โ Construct Binary Tree from Preorder and Inorder โ Construct Binary Tree from Inorder and Postorder.
Construct Binary Tree from Inorder and Postorder
Core idea: Postorder is
(Left, Right, Root), so its last element is always the root. Locate that root inside the inorder array to split inorder into a left part and a right part โ everything left of the root belongs to the left subtree, everything right belongs to the right subtree. Recurse, and you've rebuilt the whole tree.
Problem, rephrased
You're given two integer arrays for the same binary tree, both listing every node exactly once with distinct values:
inorderโ the values in Left โ Root โ Right order.postorderโ the values in Left โ Right โ Root order.
Reconstruct the original tree and return its root. Because the values are distinct, the two orderings together pin down exactly one tree.
Forget abstract nodes for a moment. Imagine you're a build engineer staring at two logs of the same dependency build. The postorder log is the completion log: a parent task can only finish after both of its child subtrees finish, so the parent is recorded last โ and the very last line of the whole log is the top-level target that finished last of all. The inorder log records tasks in a left-to-right scan of the dependency layout, so once you know which task is the top-level target, every task logged before it sits in its left branch and every task logged after it sits in its right branch. Reading the completion log from the bottom up, and using the layout log to decide who goes left and who goes right, you can redraw the entire build graph.
Here's a small instance as data, and the unique tree it encodes:
inorder |
postorder |
Resulting tree (ASCII) |
|---|---|---|
[9, 3, 15, 20, 7] |
[9, 15, 7, 20, 3] |
3 |
[2, 1] |
[2, 1] |
1 |
[ ] (empty) |
[ ] (empty) |
empty tree (None) |
In the first row, postorder[-1] = 3 is the root. Finding 3 in inorder splits it into [9] (left subtree) and [15, 20, 7] (right subtree). Recurse on each side and the tree falls out.
Sign in to continue reading
The rest of this lesson is available with a free account. Signing in with Google or Microsoft is free.
Sign in to read the full lesson