Given an n-ary tree, return the level order traversal of its nodes' values.
Nary-Tree input serialization is represented in their level order traversal, each group of children is separated by the null value (See examples).
Example 1:
Input: root = [1,null,3,2,4,null,5,6] Output: [[1],[3,2,4],[5,6]]
Example 2:
Input: root = [1,null,2,3,4,5,null,null,6,7,null,8,null,9,10,null,null,11,null,12,null,13,null,null,14] Output: [[1],[2,3,4,5],[6,7,8,9,10],[11,12,13],[14]]
Constraints:
1000
[0, 104]
This problem asks for a level order traversal of an N-ary tree. Level order traversal means visiting all nodes at a given level before moving to the next level. Because of the tree's structure, Breadth-First Search (BFS) is the natural approach. Depth-First Search (DFS) can also be adapted, but BFS is generally more efficient for level order traversal.
BFS uses a queue to systematically explore the tree level by level.
Algorithm:
Initialization:
ans
to store the level order traversal result (a list of lists, where each inner list represents a level).q
and add the root node to it. If the root is null
, return an empty list.Iteration:
q
is not empty:
level
to store the values of nodes at the current level.n
of the queue (the number of nodes at the current level).n
times:
q
.level
list.q
.level
list to ans
.Return:
ans
list.Time Complexity: O(N), where N is the number of nodes in the tree. Each node is visited and processed exactly once.
Space Complexity: O(W), where W is the maximum width (number of nodes) at any level of the tree. In the worst case (a complete tree), W can be proportional to N.
Code (Python):
from collections import deque
class Node:
def __init__(self, val=None, children=None):
self.val = val
self.children = children
class Solution:
def levelOrder(self, root: 'Node') -> List[List[int]]:
ans = []
if not root:
return ans
q = deque([root])
while q:
level = []
for _ in range(len(q)):
node = q.popleft()
level.append(node.val)
q.extend(node.children)
ans.append(level)
return ans
Code (Java):
import java.util.*;
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;
}
};
class Solution {
public List<List<Integer>> levelOrder(Node root) {
List<List<Integer>> ans = new ArrayList<>();
if (root == null) return ans;
Queue<Node> q = new LinkedList<>();
q.offer(root);
while (!q.isEmpty()) {
List<Integer> level = new ArrayList<>();
int n = q.size();
for (int i = 0; i < n; i++) {
Node node = q.poll();
level.add(node.val);
if (node.children != null) q.addAll(node.children);
}
ans.add(level);
}
return ans;
}
}
While BFS is more natural for level order traversal, DFS can also be adapted. We need to track the current level during the traversal.
Algorithm:
Initialization:
ans
to store the result.dfs(node, level)
.DFS Helper Function:
node
is null
, return.level
is greater than or equal to the size of ans
, append a new empty list to ans
.ans[level]
.dfs
for each child, incrementing the level
.Main Function:
dfs(root, 0)
to start the traversal.ans
.Time Complexity: O(N), same as BFS.
Space Complexity: O(H), where H is the height of the tree. The space usage is dominated by the recursion stack, whose depth is at most H. In the worst case (a skewed tree), H can be N.
Code (Python):
class Solution:
def levelOrder(self, root: 'Node') -> List[List[int]]:
ans = []
def dfs(node, level):
if not node:
return
if level >= len(ans):
ans.append([])
ans[level].append(node.val)
for child in node.children:
dfs(child, level + 1)
dfs(root, 0)
return ans
Both BFS and DFS solutions have the same time complexity, but BFS generally uses less space for level order traversal, especially for wider trees. Choose BFS for better space efficiency in most cases.