1 minute read

Problem Statement

problem

Intuition

When faced with a tree traversal problem, I first thought about how postorder traversal works: I need to visit all the children of a node before visiting the node itself. This “bottom-up” approach naturally led me to think of recursion as a fitting solution.

Approach

To solve the problem, I decided to use a helper function that recursively traverses the tree. The helper function starts from the root node, recursively visits each child, and finally appends the value of the current node to the result list. By doing this recursively, I ensure that I process all children before the parent node, which aligns perfectly with the postorder traversal definition.

Complexity

  • Time complexity: The time complexity of this approach is \(O(n)\), where n is the number of nodes in the tree. This is because I visit each node exactly once.
  • Space complexity: The space complexity is \(O(n)\) in the worst case due to the call stack during recursion, especially in cases where the tree is highly unbalanced (e.g., a tree that is essentially a linked list).

Code

"""
# Definition for a Node.
class Node:
    def __init__(self, val=None, children=None):
        self.val = val
        self.children = children
"""

class Solution:
    def postorder(self, root: 'Node') -> List[int]:
        def helper(node, res):
            if not node:
                return
            for child in node.children:
                helper(child, res)
            res.append(node.val)
            return res
        return helper(root, [])

Editorial

Approach 1: Recursive

class Solution:
    def postorder(self, root: "Node") -> List[int]:
        result = []
        if not root:
            return result
        self._traverse_postorder(root, result)
        return result

    def _traverse_postorder(
        self, current_node: "Node", postorder_list: List[int]
    ) -> None:
        if not current_node:
            return

        # First, visit all children
        for child_node in current_node.children:
            self._traverse_postorder(child_node, postorder_list)

        # Then, add the current node's value
        postorder_list.append(current_node.val)

Approach 2: Iterative (Explicit Reversal)

class Solution:
    def postorder(self, root: "Node") -> List[int]:
        result = []

        # If the root is None, return the empty list
        if root is None:
            return result

        node_stack = [root]

        # Traverse the tree using the stack
        while node_stack:
            current_node = node_stack.pop()
            result.append(current_node.val)
            # Push all the children of the current node to the stack
            for child in current_node.children:
                node_stack.append(child)

        # Reverse the result list to get the correct postorder traversal
        result.reverse()
        return result