Want Help Cracking FAANG?

(Then click this)

×
Back to Question Bank

429. N-ary Tree Level Order Traversal - Leetcode Solution

Code Implementation

"""
# Definition for a Node.
class Node:
    def __init__(self, val=None, children=None):
        self.val = val
        self.children = children if children is not None else []
"""

from collections import deque

class Solution:
    def levelOrder(self, root: 'Node') -> List[List[int]]:
        if not root:
            return []
        result = []
        queue = deque([root])
        while queue:
            level_size = len(queue)
            level = []
            for _ in range(level_size):
                node = queue.popleft()
                level.append(node.val)
                for child in node.children:
                    queue.append(child)
            result.append(level)
        return result
      
/*
// Definition for a Node.
class Node {
public:
    int val;
    vector<Node*> children;

    Node() {}

    Node(int _val) {
        val = _val;
    }

    Node(int _val, vector<Node*> _children) {
        val = _val;
        children = _children;
    }
};
*/

class Solution {
public:
    vector<vector<int>> levelOrder(Node* root) {
        vector<vector<int>> result;
        if (!root) return result;
        queue<Node*> q;
        q.push(root);
        while (!q.empty()) {
            int size = q.size();
            vector<int> level;
            for (int i = 0; i < size; ++i) {
                Node* node = q.front(); q.pop();
                level.push_back(node->val);
                for (Node* child : node->children) {
                    q.push(child);
                }
            }
            result.push_back(level);
        }
        return result;
    }
};
      
/*
// Definition for a Node.
class Node {
    public int val;
    public List<Node> children;

    public Node() {}

    public Node(int _val) {
        val = _val;
    }

    public Node(int _val, List<Node> _children) {
        val = _val;
        children = _children;
    }
};
*/

import java.util.*;

class Solution {
    public List<List<Integer>> levelOrder(Node root) {
        List<List<Integer>> result = new ArrayList<>();
        if (root == null) return result;
        Queue<Node> queue = new LinkedList<>();
        queue.offer(root);
        while (!queue.isEmpty()) {
            int size = queue.size();
            List<Integer> level = new ArrayList<>();
            for (int i = 0; i < size; i++) {
                Node node = queue.poll();
                level.add(node.val);
                for (Node child : node.children) {
                    queue.offer(child);
                }
            }
            result.add(level);
        }
        return result;
    }
}
      
/**
 * // Definition for a Node.
 * function Node(val, children) {
 *    this.val = val;
 *    this.children = children || [];
 * };
 */

/**
 * @param {Node|null} root
 * @return {number[][]}
 */
var levelOrder = function(root) {
    if (!root) return [];
    let result = [];
    let queue = [root];
    while (queue.length > 0) {
        let size = queue.length;
        let level = [];
        for (let i = 0; i < size; i++) {
            let node = queue.shift();
            level.push(node.val);
            for (let child of node.children) {
                queue.push(child);
            }
        }
        result.push(level);
    }
    return result;
};
      

Problem Description

You are given the root of an N-ary tree (a tree where each node can have zero or more children, not just two as in a binary tree). Your task is to return the level order traversal of the tree's nodes' values. This means you should return a list of lists, where each inner list contains the values of the nodes at that level in the tree, from top to bottom and from left to right within each level.

  • The input is a single variable root representing the root node of the N-ary tree.
  • If the tree is empty (root is null), return an empty list.
  • Each node contains an integer value val and a list of children children.
  • There is only one valid traversal for a given tree.
  • Do not reuse elements or modify the tree structure.

Thought Process

The problem asks for a level order traversal, which is also known as a breadth-first traversal. For binary trees, this is commonly solved using a queue, but since this is an N-ary tree (where each node may have many children), we need to generalize the approach.

The brute-force way would be to traverse the tree and collect nodes by their depth, but this can get messy, especially with recursion. A queue-based approach is much cleaner and more efficient because it naturally processes nodes level by level.

The key insight is that for each node we process, we enqueue all its children, so that in the next round, we process all nodes at the next level together. This way, we can easily keep track of which nodes belong to which level.

Solution Approach

Let's break down the algorithm step by step:

  1. Check for an empty tree: If root is null, return an empty list immediately.
  2. Use a queue: Initialize a queue and add the root node to it. This queue will help us process nodes level by level.
  3. Iterate through the tree: While the queue is not empty, repeat the following:
    • Determine the number of nodes at the current level (the queue's length at the start of the loop).
    • For each node at this level, remove it from the queue, record its value, and enqueue all its children.
    • After processing all nodes at this level, add the list of values to the result.
  4. Return the result: Once the queue is empty, all levels have been processed, so return the final list of lists.

We use a queue (like Python's collections.deque or Java's LinkedList) because it allows O(1) append and pop operations from both ends, making the level-by-level traversal efficient.

Example Walkthrough

Consider the following N-ary tree:

           1
         / | \
        3  2  4
       / \
      5   6
  

Let's walk through the traversal step by step:

  1. Start: Queue contains [1]. Result is [].
  2. Level 1:
    • Process node 1, add its value to the level list: [1].
    • Enqueue its children [3, 2, 4].

    Result becomes [[1]].

  3. Level 2:
    • Queue now contains [3, 2, 4].
    • Process nodes 3, 2, 4: add their values [3, 2, 4].
    • Enqueue children of 3 ([5, 6]); 2 and 4 have no children.

    Result becomes [[1], [3, 2, 4]].

  4. Level 3:
    • Queue now contains [5, 6].
    • Process nodes 5, 6: add their values [5, 6].
    • They have no children, so nothing more to enqueue.

    Result becomes [[1], [3, 2, 4], [5, 6]].

  5. Done: Queue is empty. Return the result.

Time and Space Complexity

Brute-force approach: If you tried to collect nodes by their depth recursively, you would still visit each node once, but managing the result lists would be more cumbersome and could involve extra space for recursive call stacks.

Optimized queue approach:

  • Time Complexity: O(N), where N is the total number of nodes in the tree. Each node is visited exactly once.
  • Space Complexity: O(N), for the output list and the queue. In the worst case, the queue could hold all nodes at the largest level of the tree.

Summary

The N-ary Tree Level Order Traversal problem is elegantly solved using a queue for breadth-first traversal. By processing nodes level by level and collecting their values, we build the required output efficiently. The approach is both simple and optimal, leveraging the natural fit of queues for this type of traversal, and generalizes the classic binary tree level order traversal to N-ary trees with minimal changes.