{x}
blog image

N-ary Tree Preorder Traversal

Given the root of an n-ary tree, return the preorder 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,5,6,2,4]

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,6,7,11,14,4,8,12,5,9,13,10]

 

Constraints:

  • The number of nodes in the tree is in the range [0, 104].
  • 0 <= Node.val <= 104
  • The height of the n-ary tree is less than or equal to 1000.

 

Follow up: Recursive solution is trivial, could you do it iteratively?

589. N-ary Tree Preorder Traversal

This problem asks for a preorder traversal of an N-ary tree. Preorder traversal means visiting the root node first, then recursively traversing its children from left to right.

Solutions

Two approaches are presented: recursion and iteration using a stack.

Solution 1: Recursion

This is the most straightforward approach. The recursive function dfs visits a node, adds its value to the result list, and then recursively calls itself for each child.

Time Complexity: O(N), where N is the number of nodes in the tree. Each node is visited exactly once.

Space Complexity: O(H), where H is the height of the tree. This is due to the recursive call stack. In the worst case (a skewed tree), H can be equal to N. In the best case (a balanced tree), H is log₂(N).

Code (Python):

class Node:
    def __init__(self, val=None, children=None):
        self.val = val
        self.children = children
 
class Solution:
    def preorder(self, root: 'Node') -> List[int]:
        ans = []
        def dfs(node):
            if node:
                ans.append(node.val)
                for child in node.children:
                    dfs(child)
        dfs(root)
        return ans
 

The code in other languages (Java, C++, Go, TypeScript, C) follows a similar recursive structure.

Solution 2: Iteration (Stack)

This approach uses a stack to simulate the recursive calls. The root is pushed onto the stack. The loop continues as long as the stack is not empty. Each iteration pops a node, adds its value to the result, and pushes its children onto the stack in reverse order (to maintain left-to-right traversal).

Time Complexity: O(N), same as the recursive approach. Each node is visited and processed once.

Space Complexity: O(W), where W is the maximum width of the tree. In the worst-case scenario (a very wide tree), W could approach N. In the best-case scenario (a very narrow or balanced tree), W would be much smaller than N. It is still considered O(N) in the worst case.

Code (Python):

class Solution:
    def preorder(self, root: 'Node') -> List[int]:
        ans = []
        stack = [root]
        while stack:
            node = stack.pop()
            if node:
                ans.append(node.val)
                stack.extend(node.children[::-1]) # Reverse order to maintain left-to-right
        return ans

Again, the iterative approach is implemented similarly in other languages, using stack data structures appropriate for each language (e.g., Deque in Java, stack in C++).

In Summary:

Both recursive and iterative solutions have a time complexity of O(N). The recursive solution has a space complexity of O(H) (height of the tree), while the iterative solution has a space complexity of O(W) (maximum width of the tree). The choice between them depends on the specific characteristics of the input trees and the coding style preference. For very deep, narrow trees, recursion might be slightly more efficient in space. For very wide trees, the iterative approach might be preferred. For most cases, the difference is negligible.