Skip to content
← All posts

N-ary Tree Level Order Traversal: BFS Beyond Binary Trees

5 min read
leetcodeproblemmediumtrees

Given an n-ary tree, return the level order traversal of its nodes' values. That means collecting values from left to right, level by level. Each node can have any number of children, not just two. This is LeetCode 429: N-ary Tree Level Order Traversal.

For example, given the tree below with root = 1, children [3, 2, 4], and node 3 having children [5, 6], the output is [[1], [3, 2, 4], [5, 6]].

Level 0Level 1Level 2132456Output: [[1], [3, 2, 4], [5, 6]]
An n-ary tree with root 1. Each node can have any number of children. BFS processes each level left to right.

Why this problem matters

If you have solved Binary Tree Level Order Traversal (LeetCode 102), you already know the core BFS pattern: use a queue, snapshot the level size, drain one level at a time. This problem asks you to generalize that pattern from binary trees to n-ary trees.

The difference is small but important. In a binary tree, each node has at most two children (node.left and node.right). In an n-ary tree, each node has a list of children (node.children). Instead of checking two fixed pointers, you iterate over a list. That single change is what separates the two problems.

This generalization shows up in real-world scenarios more often than binary trees do. File systems, organizational charts, and DOM trees are all n-ary. Once you can BFS an n-ary tree, you can BFS any tree structure.

The approach

The algorithm is the same level-by-level BFS you already know, adapted for n-ary children:

  1. Start with the root in a list (acting as the initial queue).
  2. While the queue is not empty, iterate through every node in the current queue. For each node, collect its value and extend a next-level list with all of its children.
  3. Append the collected values as a level and swap the queue for the next-level list.
def levelOrder(root):
    if not root:
        return []

    result = []
    queue = [root]

    while queue:
        level = []
        next_queue = []
        for node in queue:
            level.append(node.val)
            next_queue.extend(node.children)
        result.append(level)
        queue = next_queue

    return result

Here is what each part does:

  • queue = [root] seeds the queue with the root node. Level 0 always has exactly one node.
  • The for loop walks through every node at the current level. It collects each value and pushes all children into next_queue.
  • next_queue.extend(node.children) is the key difference from binary tree BFS. Instead of checking node.left and node.right, you add all children at once.
  • queue = next_queue replaces the current level with the next, so the outer loop processes one level per iteration.

This version uses a plain list instead of a deque. Since we never call pop(0) on the queue (we iterate through it and then replace it entirely), there is no O(n) penalty. Each node is visited exactly once.

Step-by-step walkthrough

Let's trace BFS through the n-ary tree with root 1, children [3, 2, 4], and node 3 having children [5, 6]. Watch how the queue drains one level at a time and the output builds up level by level.

Step 1: Initialize. Push root into the queue.

132456

Queue: [1]

Output: []

The queue holds the root. We are about to process level 0.

Step 2: Process Level 0. Dequeue 1, enqueue its children.

132456

Queue: [3, 2, 4]

Output: [[1]]

Node 1 is processed. Its three children (3, 2, 4) are added to the queue for the next level.

Step 3: Process Level 1. Dequeue 3, 2, and 4.

132456

Queue: [5, 6]

Output: [[1], [3, 2, 4]]

All three nodes at level 1 are processed. Node 3 adds children 5 and 6. Nodes 2 and 4 have no children.

Step 4: Process Level 2. Dequeue 5 and 6.

132456

Queue: []

Output: [[1], [3, 2, 4], [5, 6]]

Both are leaves with no children. Nothing new enters the queue.

Step 5: Queue is empty. Done!

132456

Queue: []

Output: [[1], [3, 2, 4], [5, 6]]

All nodes visited. The output contains one list per level, left to right.

Notice the rhythm. At each step, you drain the entire current level from the queue, collect the values, and push all children for the next level. Once the queue is empty, every level has been captured.

Complexity analysis

MetricValueWhy
TimeO(n)Every node is visited exactly once in the BFS loop
SpaceO(n)The queue can hold up to the widest level of the tree

The space is O(n) in the worst case because a very wide, shallow tree could have most of its nodes on a single level. For a deep, narrow tree, the queue never holds more than a few nodes at once. But we express the worst case as O(n).

Edge cases to watch for

  • Empty tree (root is None): return an empty list []. The guard clause at the top handles this.
  • Single node (no children): return [[root.val]]. The queue starts with one node, processes it, finds no children, and the loop ends after one level.
  • Node with many children: the algorithm handles any number of children naturally because extend(node.children) works for lists of any length.
  • Deep unbalanced tree: each level may have only one node, producing [[a], [b], [c], ...]. No special logic needed.

The building blocks

This problem is built on one core pattern: BFS level-by-level processing. The only twist compared to binary tree BFS is iterating over node.children instead of checking node.left and node.right.

Once you internalize the level-by-level BFS template, you can apply it across a family of related problems:

The n-ary version reinforces that BFS does not depend on a fixed branching factor. The template works on any tree as long as you can enumerate a node's children.

From understanding to recall

You just walked through a clean BFS solution and watched the queue drain level by level. The logic is clear right now. But when you face a variation of this problem in an interview next month, will you remember to use extend(node.children) instead of checking left and right? Will you reconstruct the level-by-level template without hesitation?

Understanding a pattern and being able to reproduce it under pressure are different skills. Spaced repetition bridges that gap. You practice the BFS level-by-level template from memory at increasing intervals. First after a day, then three days, then a week. Each repetition reinforces the queue management, the level snapshot, and the children iteration until it becomes automatic.

BFS level-by-level is one of roughly 60 reusable building blocks that cover hundreds of LeetCode problems. Drilling them individually with spaced repetition is far more effective than grinding random problems and hoping the patterns stick.

Related posts