A binary tree can be traversed in preorder, inorder, postorder or level-order.
Among these traversal methods, preorder, postorder and level-order traversal are suitable to be extended to an N-ary
tree.
Retrospect - Traverse a Binary Tree
- Preorder Traversal: Visit the root node, then traverse the left subtree and finally traverse the right subtree.
- Inorder Traversal: Traverse the left subtree, then visit the root node and finally traverse the right subtree.
- Postorder Traversal: Traverse the left subtree, then traverse the right subtree and finally visit the root node.
- Level-order Traversal: Traverse the tree level by level.
Traverse the left subtree…. Traverse the right subtree….
in the above by:
For each child: Traverse the subtree rooted at that child by recursively calling the traversal function
We assume that the for-loop will iterate through the children in the order they are found in the data-structure: typically, in left-to-right order, for a diagram such as below.
We will use the following 3-ary tree as example:
In an N-ary tree, preorder means visit the root node first and then traverse the subtree rooted at its children one by one. For instance, the preorder of the 3-ary tree above is: A->B->C->E->F->D->G.
In an N-ary tree, postorder means traverse the subtree rooted at its children first and then visit the root node itself. For instance, the postorder of the 3-ary tree above is: B->E->F->C->G->D->A.
Level-order traversal in an N-ary tree is the same with a binary tree. Typically, when we do breadth-first search in a tree, we will traverse the tree in level order. For instance, the level-order of the 3-ary tree above is: A->B->C->D->E->F->G.
Given 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:
1000
[0, 10^4]
Code:
from typing import List
from collections import deque
class Node:
def __init__(self, val=None, children=None):
self.val = val
self.children = []
class Solution:
def preorder(self, root: 'Node') -> List[int]:
# return self.preorder_recursive(root, [])
return self.preorder_iterative(root)
def preorder_recursive(self, root, result):
if(root):
result.append(root.val)
for node in root.children:
self.preorder_recursive(node, result)
return result
def preorder_iterative(self, root):
result = []
stack = deque()
if root:
stack.append(root)
while (stack):
current = stack.pop()
result.append(current.val)
for i in range(len(current.children) - 1, -1, -1):
stack.append(current.children[i])
return result
root = Node(1)
root.children.append(Node(3))
root.children.append(Node(2))
root.children.append(Node(4))
root.children[0].children.append(Node(5))
root.children[0].children.append(Node(6))
print(Solution().preorder(root))
Output:
[1, 3, 5, 6, 2, 4]
Given an n-ary tree, return the postorder 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: [5,6,3,2,4,1]
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: [2,6,14,11,7,3,12,8,4,13,9,10,5,1]
Constraints:
1000
[0, 10^4]
Code:
from typing import List
from collections import deque
class Node:
def __init__(self, val=None, children=None):
self.val = val
self.children = []
class Solution:
def postorder(self, root: 'Node') -> List[int]:
result = []
stack = deque()
if root:
stack.append(root)
while (stack):
current = stack[-1]
if current.children:
for i in range(len(current.children) - 1, -1, -1):
stack.append(current.children[i])
current.children = []
else:
result.append(stack.pop().val)
return result
root = Node(1)
root.children.append(Node(3))
root.children.append(Node(2))
root.children.append(Node(4))
root.children[0].children.append(Node(5))
root.children[0].children.append(Node(6))
print(Solution().postorder(root))
Output:
[5, 6, 3, 2, 4, 1]
Given an n-ary tree, return the postorder 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]]
Code:
from typing import List
from collections import deque
class Node:
def __init__(self, val=None, children=None):
self.val = val
self.children = []
class Solution:
def levelOrder(self, root: 'Node') -> List[List[int]]:
queue = deque()
result = []
if root:
queue.append(root)
while (queue):
n = len(queue)
curr_level = []
for i in range(n):
current = queue.popleft()
curr_level.append(current.val)
for child in current.children:
queue.append(child)
result.append(curr_level)
return result
root = Node(1)
root.children.append(Node(3))
root.children.append(Node(2))
root.children.append(Node(4))
root.children[0].children.append(Node(5))
root.children[0].children.append(Node(6))
print(Solution().levelOrder(root))
Output:
[[1], [3, 2, 4], [5, 6]]
Given an n-ary tree, ind its maximum depth.
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: 3
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: 5
Code:
from typing import List
from collections import deque
class Node:
def __init__(self, val=None, children=None):
self.val = val
self.children = []
class Solution:
def maxDepth(self, root: 'Node') -> int:
if not root:
return 0
max_children_depth = 0
for child in root.children:
max_children_depth = max(max_children_depth, self.maxDepth(child))
return 1 + max_children_depth
root = Node(1)
root.children.append(Node(3))
root.children.append(Node(2))
root.children.append(Node(4))
root.children[0].children.append(Node(5))
root.children[0].children.append(Node(6))
print(Solution().maxDepth(root))
Output:
3