EasyTrees

Binary Tree Postorder Traversal โ€” Solution

Problem

Given the root of a binary tree, visit every node and collect the values in postorder: fully process the left subtree, then the right subtree, then the root. The root of any subtree is always the last node reported from that subtree.

12453
[1,2,3,4,5]
  • Input: root = [1, 2, 3, 4, 5]
  • Output: [4, 5, 2, 3, 1]
  • Explanation: left subtree yields 4 โ†’ 5 โ†’ 2, right subtree yields 3, root yields 1 last.

Compare with the single-right-child tree below โ€” postorder here is [3, 2, 1] because node 3 (deepest left child of 2) finishes before 2 finishes before 1.

12
[1,null,2,null,null,3]

Intuition

Postorder is the natural order for "bottom-up" processing โ€” a node's result depends on its children being done first. Recursion expresses this directly: define the traversal of any subtree as (left subtree) + (right subtree) + (root value), and the call stack handles the ordering automatically with no extra bookkeeping.

Solution โ€” Recursive DFS

Recursively traverse the left subtree, then the right subtree, then append the current node's value. The base case returns immediately on a null node.

  1. If the current node is null, return โ€” this handles both empty trees and leaf boundaries.
  2. Recurse into the left child.
  3. Recurse into the right child.
  4. Append the current node's value to the result list.
  5. Return the accumulated list after the initial call returns.
1def postorderTraversal(root: "TreeNode") -> list[int]:
2    result = []
3
4    def traverse(node: "TreeNode") -> None:
5        if not node:
6            return
7        traverse(node.left)       # finish entire left subtree first
8        traverse(node.right)      # then entire right subtree
9        result.append(node.val)   # root of this subtree is always last
10
11    traverse(root)
12    return result

Time: O(n) โ€” every node is visited exactly once. Space: O(h) โ€” the call stack reaches the height of the tree; O(log n) for a balanced tree, O(n) for a skewed one.

Complexity Summary

ApproachTimeSpaceWhen to use
Recursive DFSO(n)O(h)All practical cases; clean and direct expression of the algorithm

Common Mistakes

  • Appending the node value before recursing โ€” that produces preorder (root โ†’ left โ†’ right), not postorder. The append must come after both recursive calls return.
  • Confusing the three traversal orders โ€” postorder is left โ†’ right โ†’ root; inorder is left โ†’ root โ†’ right; preorder is root โ†’ left โ†’ right. Postorder is the only one where the root is always last.
  • Missing the null base case โ€” without if not node: return, the recursion crashes on null children of leaf nodes. This is the single most common runtime error on tree problems.
  • Returning the inner function's value instead of the outer list โ€” in Python, the inner traverse function returns None; the result accumulates in the shared result list, which the outer function returns. Doing return traverse(root) returns None.
  • Assuming the output order equals insertion order in a set or dict โ€” the traversal order must come from the recursion structure, not from any collection with undefined iteration order.

Related Problems

Ready to practice? Try it on SkillFlow

Adaptive problems, AI follow-up interviews, and a skill score that shows exactly where you need to improve.

Practice This Problem โ†’