Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 25

Level-Order Tree Traversal with Queues

Recommended resources

Hello! Welcome to our lesson on tree traversals.

In our last session, we mastered using a deque to solve the Sliding Window Maximum problem, seeing how it could maintain an ordered set of candidates efficiently. Today, we'll leverage the deque again, but this time in its most fundamental role: as a queue. We will apply it to a new data structure—the binary tree—to implement one of the most important traversal algorithms.

Your goal for this lesson is to learn how to use a queue to implement the level-order traversal of a tree. This technique is also known as Breadth-First Search (BFS) and is a cornerstone of tree and graph algorithms. It's a frequent topic in technical interviews, and mastering it is essential for solving a wide range of problems involving trees.

1. The Core Idea: Breadth-First Traversal with a Queue

Level-order traversal means visiting all nodes at a given depth (or "level") before moving on to the next level. Within each level, nodes are typically visited from left to right.

For the tree below, the level-order traversal would be: [3], [9, 20], [15, 7].

How do we enforce this level-by-level, left-to-right order? The answer lies in the First-In, First-Out (FIFO) behavior of a queue.

The core logic is:

  1. Start by adding the root node to the queue.
  2. While the queue is not empty:
    a. Remove the node from the front of the queue.
    b. Process this node (e.g., add its value to our result).
    c. Add its children (left, then right) to the back of the queue.

By adding children to the back and always processing from the front, we guarantee that we process all nodes at level k before we ever get to the nodes at level k+1, which were added later.

The following video provides an excellent visual introduction to this concept.

Binary Tree Level Order Traversal - BFS - Leetcode 102

The video 'Binary Tree Level Order Traversal' by NeetCode starts by explaining what level-order traversal is and why Breadth-First Search (BFS) with a queue is the right algorithm for the job.

Please watch from the beginning up to 02:41. Focus on understanding the problem and the fundamental role of the queue's FIFO property in achieving a level-by-level traversal.

This image provides a great visual summary of the process, showing how nodes move from "Not traversed" to "Inside the queue" and finally to "Already Traversed".

Level-Order Tree Traversal with Queue Visualization
This image illustrates a step in a level-order traversal. Nodes that have been processed are green, nodes currently in the queue are yellow, and nodes yet to be visited are grey. The queue at the bottom shows the nodes for the next level waiting to be processed in order.

2. The Algorithm: Grouping Nodes by Level

In many interview problems (like LeetCode 102), you aren't just asked to traverse the nodes, but to return them grouped by level, like [[3], [9, 20], [15, 7]]. The basic BFS approach we just discussed gives us a single flat list. So, how do we know when one level ends and the next begins?

The solution is an elegant and widely used pattern:
Before processing a level, we record the current size of the queue. This number tells us exactly how many nodes are in the current level. We then loop that many times to process all nodes of that level, adding their children to the queue for the next level.

Here's the refined algorithm:

  1. Initialize a result list and a queue with the root node.
  2. While the queue is not empty:
    a. Get the current size of the queue (level_size).
    b. Create a current_level list to store this level's node values.
    c. Loop level_size times:
    i. Dequeue a node.
    ii. Add its value to the current_level list.
    iii. Enqueue its non-null children (left first, then right).
    d. Once the loop finishes, add the current_level list to the result list.
  3. Return the result.

The following reading explains this exact pattern clearly and concisely.

Breadth-First Search Fundamentals

The article 'Breadth-First Search Fundamentals' from HelloInterview provides a perfect, focused explanation of this level-grouping technique.

Please read the section titled 'Processing Levels'. It presents the exact Python code and logic for extending basic BFS to group nodes by level, which is the standard interview pattern.

Test your understanding!

Given the following tree, trace the state of the queue and result list as the level-order algorithm executes.

    1
   / \
  2   3
 /   / \
4   5   6

What are the contents of result and queue just before processing Level 2 (the one with nodes 4, 5, 6)?

Show answer
  1. Initial: result = [], queue = deque([node(1)])
  2. Start Level 0: level_size = 1. current_level = [].
    • Dequeue node(1), current_level = [1]. Enqueue node(2), node(3). queue = deque([node(2), node(3)]).
    • Level 0 finished. result = [[1]].
  3. Start Level 1: level_size = 2. current_level = [].
    • Dequeue node(2), current_level = [2]. Enqueue node(4). queue = deque([node(3), node(4)]).
    • Dequeue node(3), current_level = [2, 3]. Enqueue node(5), node(6). queue = deque([node(4), node(5), node(6)]).
    • Level 1 finished. result = [[1], [2, 3]].

Answer: Just before processing Level 2, the state is:

  • result = [[1], [2, 3]]
  • queue = deque([node(4), node(5), node(6)])

3. Implementation and Complexity Analysis

Now let's put it all together in code. As you're proficient in Python, we'll use collections.deque, which you're already familiar with from our last lesson. It provides the O(1) popleft() and append() operations we need for an efficient queue.

This video walks through the implementation logic and the final Python code.

Binary Tree Level Order Traversal - BFS - Leetcode 102

Let's return to the NeetCode video to see a detailed walkthrough and the final Python implementation.

Watch from 02:41 to 05:46 for a detailed dry run of the algorithm. Then, watch the coding part from 06:36 to 09:21 to see how this logic translates into clean Python code.

Here is a typical Python implementation, reflecting the algorithm we've discussed:

from collections import deque
from typing import List, Optional

# Definition for a binary tree node.
class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

class Solution:
    def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
        if not root:
            return []

        result = []
        queue = deque([root])

        while queue:
            level_size = len(queue)
            current_level = []

            for _ in range(level_size):
                node = queue.popleft()
                current_level.append(node.val)
                
                if node.left:
                    queue.append(node.left)
                if node.right:
                    queue.append(node.right)
            
            result.append(current_level)
            
        return result

Complexity Analysis

Understanding the performance of your algorithms is crucial for interviews.

  • Time Complexity: O(N)
    We visit every node in the tree exactly once (it's enqueued once and dequeued once). The operations inside the loop (append, popleft, check children) are all O(1). Therefore, the total time is directly proportional to the number of nodes, N.

  • Space Complexity: O(W) or O(N)
    The space is determined by the maximum number of nodes stored in the queue at any one time. This corresponds to the maximum width (W) of the tree. In the worst-case scenario (a complete, balanced binary tree), the last level can contain up to (N+1)/2 nodes. Therefore, the space complexity is O(N). The result list also takes O(N) space, but auxiliary space complexity for interviews typically focuses on data structures like the queue.

For a final review of these concepts, including common pitfalls to avoid during an interview (like using a list's pop(0) which is O(N)), you can skim the "Solution Approach", "Time and Space Complexity", and "Common Pitfalls" sections in the Algo.monster article (ID LINK).


Conclusion

Excellent work! You have successfully learned how to implement level-order traversal, a fundamental BFS application for trees. This pattern is not just a standalone problem but a building block for many others, such as finding the minimum depth of a tree, checking for completeness, or solving "cousin" node problems.

Key Takeaways:

  • Level-order traversal is BFS applied to a tree.
  • A queue is the essential data structure due to its FIFO property. In Python, collections.deque is the optimal choice.
  • To group nodes by level, use the level_size = len(queue) trick to snapshot the number of nodes at the start of each level's processing.
  • The algorithm has a time complexity of O(N) and a space complexity of O(W) (maximum width), which is O(N) in the worst case.

In our next lesson, we will explore the other major category of tree traversals: Depth-First Search (DFS). We will implement the three classic recursive DFS traversals: pre-order, in-order, and post-order.