Notes & software courses · Free to learn
Aph's Blog

LC872 Leaf-Similar Trees 🟢

👋 อ่านฟรีทั้งหมดบน Aph's Blog — เนื้อหาภาษาไทย ทำตามทีละหน้าใน sidebar ได้เลย หากมีข้อเสนอแนะหรืออยากให้เพิ่มหัวข้อไหน บอกได้เสมอ

Tree = maze · Leaf = dead end — DFS left-first, collect dead ends left-to-right, then compare the two boxes.

Consider all the leaves of a binary tree, from left to right order, forming a leaf value sequence.

Two binary trees are considered leaf-similar if their leaf value sequences are the same.

Return true if and only if the two given trees with head nodes root1 and root2 are leaf-similar.

Example 1
Input:
root1 = [3,5,1,6,2,9,8,null,null,7,4], root2 = [3,5,1,6,7,4,2,null,null,null,null,null,null,9,8]
Output:
true
Explanation:
Both trees share the same leaf sequence [6,7,4,9,8] even though their shapes differ.
Example 2
Input:
root1 = [1,2,3], root2 = [1,3,2]
Output:
false
Explanation:
First tree leaf sequence [2,3]; second [3,2] — order differs, so not leaf-similar.
Constraints (ข้อจำกัด)
  • The number of nodes in each tree is in the range [1, 200].
  • 0 <= Node.val <= 200
Full solution · Try yourself firstพับไว้ด้านใน — คลิกเมื่อพร้อมดู

This matches the "collect then compare" pattern — walk the maze, fill boxes with dead ends, then check if the two boxes match.

1. Problem Decoding

We have two Binary Trees (root1 and root2).
Mission: walk in and collect Leaf Node values (tip nodes with no children), left to right.

If the leaf list of the first tree matches the second tree position-by-position, return True; otherwise False.

2. Mental Model

Picture the Tree as a "maze":

  • Root: the entrance door
  • Node: a fork / junction
  • Leaf: a "dead end" (nowhere left or right to go)

We'll use DFS (Depth-First Search) with these maze rules:

  1. Always turn left first
  2. When you hit a "dead end (Leaf)", put the wall number in the box (List), then walk back (Return)
  3. Back at the fork, then explore the right branch

3. Logic-to-Code Mapping

We'll write get_leaves(node) to walk the maze, handling three situations:

Situation 1: Fall off the edge (no branch)

When a branch doesn't exist, the computer sees Null / None. Tell it: "nothing to collect — send back an empty box."

Situation 1python
# If node is empty (this branch doesn't exist)
if not node:
    return []  # send back an empty List

Situation 2: Dead end (it's a Leaf!)

Our main goal! A dead end means the Node you're on has no left child and no right child. Put this Node's number in the box and return it upward.

Situation 2python
# No left child and no right child
if not node.left and not node.right:
    return [node.val]  # put the number in a List and Return

Situation 3: A fork (keep exploring)

If it's not a dead end, it's a fork. Rule: "left first, then right." Recurse left, then right, then pour the boxes together (Python + concatenates Lists).

Situation 3python
# Take the left box, concatenate the right box
return get_leaves(node.left) + get_leaves(node.right)

4. Step-by-Step Walkthrough

Suppose the Tree looks like this, and we call get_leaves:

        3
       / \
      5   1
     / \
    6   2
  1. Start (Root): Node 3 — not a dead end → Situation 3: "left box + right box", dive to node.left (5)
  2. Left branch: Node 5 — not a dead end, dive left again (to 6)
  3. First Leaf!: Node 6 — Situation 2 → box [6], Return up to Node 5
  4. Second Leaf!: Node 2 — Node 5 got the left box, explores right, hits 2 → Situation 2 → box [2], Return to Node 5
  5. Merge at fork: Node 5 — left + right → [6] + [2] = [6, 2], Return big box up to Root 3
  6. Right of Root: Node 1 — Root 3 explores right, hits 1 → Situation 2 → box [1], Return to Root 3
  7. Finale: Node 3 — left + right → [6, 2] + [1] = [6, 2, 1]

5. Full Assembled Code

Glue the three pieces into LeetCode's Solution class — short, clean, logic transparent:

Submit this on LeetCodepython
class Solution:
    def leafSimilar(self, root1: Optional[TreeNode], root2: Optional[TreeNode]) -> bool:

        # DFS maze walker
        def get_leaves(node):
            # 1. Fall off the edge
            if not node:
                return []

            # 2. Dead end (Leaf Node)
            if not node.left and not node.right:
                return [node.val]

            # 3. Fork: left box + right box
            return get_leaves(node.left) + get_leaves(node.right)

        # Compare leaf boxes of both trees
        return get_leaves(root1) == get_leaves(root2)

6. Complexity

  • Time Complexity: O(T₁ + T₂) where T is each tree's node count — DFS steps on every node exactly once
  • Space Complexity: O(L₁ + L₂ + H) — L for the leaf Lists, H for the recursive Call Stack that remembers the walk-back path
💡 Pattern summary

DFS always left-first → left-to-right leaves for free · collapse the maze into comparing two boxes (Lists).