Lesson 30 — Trees III: walking two trees at once

~20 minutes · Day 33 · simultaneous DFS

Tonight's interview move is small but important: sometimes one recursive call is not enough. In Same Tree, the question is not "what is the answer for one subtree?" It is "do these two current positions describe the same tree?" That means every step carries two nodes, not one.

The invariant

Two trees are identical iff their roots match and both pairs of subtrees are identical — compare them in lockstep.

That sentence is the whole pattern. Do not try to remember a special trick for Same Tree. Remember the lockstep question: compare the two current roots, then compare left with left and right with right.

Same Tree: carry a pair of nodes 1 2 3 1 2 3 p q root with root left with left right with right Key insight: one recursive call receives two current nodes.

Lockstep DFS keeps the two current positions together, so shape and values are checked at the same time.

Same Tree: the bulky way first

The blunt approach is serialize-and-compare: turn each tree into a preorder list with explicit null markers, then compare the two lists. That works because null markers preserve shape, but it spends O(n + m) extra space building two full representations before the comparison is finished. The problem statement gives two binary-tree roots, so we can compare those roots directly instead.

Same Tree: the lockstep way

A recursive DFS is a natural fit for trees: answer the question at this pair of nodes, then trust the same question on the paired children. Python's boolean operators also short-circuit, so the second subtree check is skipped if the first already proves failure (Python docs: boolean operations).

def isSameTree(p, q):
    if not p and not q:
        return True                  # both empty: same here
    if not p or not q:
        return False                 # one empty: shapes differ
    if p.val != q.val:
        return False                 # roots differ
    return (isSameTree(p.left, q.left) and
            isSameTree(p.right, q.right))  # paired children

The order matters. Empty-vs-empty is success. Empty-vs-node is failure. Two nodes with different values are failure. Only after those checks do the child pairs get a vote.

Transfer: same question, new costume

Symmetric Tree: is a tree a mirror of itself?

Before opening the reveal: what should the paired recursive calls compare? Say the two pairs out loud.

Your prediction first — then reveal.

Use the same lockstep shape, but compare mirror pairs. The root's left subtree must match the root's right subtree. Inside that helper, values match, then left.left pairs with right.right, and left.right pairs with right.left. Same invariant; different pairing rule.

Symmetric Tree: same pattern, crossed pairs root L R LL LR RL RR L with R LL with RR LR with RL Key insight: mirror DFS crosses the child pairs.

The helper still carries two nodes; only the pairing rule changes from same-side to mirror-side.

What the trade buys you

ApproachTimeSpace
Serialize both trees firstO(n + m)O(n + m)
Lockstep DFS comparisonO(n + m)O(h)

Worst-case time is still linear because matching trees must be fully checked. The win is cleaner reasoning, early failure on the first mismatch, and only the recursion stack instead of two stored traversals. Here h is the height of the recursion stack.

Practice — answer before you scroll past

1. Which line best states this pattern?

2. Spot the bug in this base case:

if not p or not q:
    return True

3. What should two null children return?

4. Which task reuses lockstep comparison?

Your move (Day 33)

Solve Same Tree tonight, logging it in your Notion tracker with the cycle — predict → attempt → compare → encode:

  1. Predict: name the pattern, state the serialize-and-compare brute force, then state the lockstep invariant.
  2. Attempt: write the three base checks before the child recursion.
  3. Compare: watch the source below only after your attempt.
  4. Encode: write the invariant from this page and the DFS-with-return-value template in your own words.
Primary source

Watch NeetCode — Same Tree after your attempt, as the compare step. Find the exact moment where his base-case reasoning matches or differs from yours.