AlgoMaster Logo

Binary Tree Postorder Traversal

Last Updated: March 29, 2026

easy
4 min read

Understanding the Problem

We need to traverse a binary tree in postorder, which means: visit the left subtree first, then the right subtree, then the current node. This is the opposite of preorder (root, left, right) and different from inorder (left, root, right).

Postorder traversal has a natural recursive definition, which makes the recursive solution almost trivial. But the real challenge, and the reason interviewers ask this problem, is implementing it iteratively. Unlike preorder and inorder, postorder is the trickiest of the three traversals to do without recursion. The difficulty comes from the fact that we need to visit the root last, but we encounter it first as we descend the tree. We need to somehow "remember" to come back to a node after both its subtrees have been processed.

The key observation is that postorder (left, right, root) is the reverse of a modified preorder (root, right, left). This insight unlocks an elegant iterative solution.

Key Constraints:

  • Number of nodes in range [0, 100] → Extremely small input. Even an O(n^2) solution would run in microseconds. The focus here isn't on optimization but on correctly implementing the traversal, especially iteratively.
  • -100 <= Node.val <= 100 → Node values can be negative. This doesn't affect traversal logic but ensures our solution handles negative values in the output.
  • The tree can be empty (0 nodes), so we need a null root check.

Approach 1: Recursive DFS

Intuition

Postorder traversal is defined recursively: visit the left subtree, visit the right subtree, then visit the root. So the recursive solution writes itself. You just follow the definition: recurse left, recurse right, add the current node's value to the result.

This is the solution most people write first, and it's perfectly correct. The recursion handles the "come back to the root after both subtrees" problem automatically through the call stack. When the left recursive call returns, the right one starts. When the right one returns, we add the current node. The call stack is doing all the bookkeeping for us.

Algorithm

  1. If the root is null, return an empty list.
  2. Create a result list.
  3. Define a recursive helper postorder(node):
    • If node is null, return.
    • Recurse on the left child.
    • Recurse on the right child.
    • Add node.val to the result.
  4. Call postorder(root) and return the result.

Example Walkthrough

1Start postorder(1): go left first
1current23
1/6

Code

The recursive solution is correct and optimal in time, but it relies on the call stack. For very deep trees, this could cause a stack overflow.

Can we eliminate the recursion and manage the stack ourselves?

Approach 2: Iterative with Reverse Modified Preorder

Intuition

Here's the clever observation that makes iterative postorder much easier than it first appears. Consider what happens if you do a modified preorder traversal where you visit the root, then the right child, then the left child. That gives you: root, right, left. Now reverse that result, and you get: left, right, root. That's postorder.

So instead of wrestling with the tricky question of "when is it safe to pop a node," we can sidestep the problem entirely. Do a modified preorder (which is straightforward with a stack), then reverse the output.

Algorithm

  1. If the root is null, return an empty list.
  2. Create a stack and push the root onto it.
  3. Create a result list.
  4. While the stack is not empty:
    • Pop a node from the stack.
    • Add its value to the result.
    • If the node has a left child, push it onto the stack.
    • If the node has a right child, push it onto the stack.
  5. Reverse the result list and return it.

We push left before right. Since a stack is LIFO, the right child gets popped first. This gives us root-right-left traversal order. Reversing produces left-right-root, which is postorder.

Example Walkthrough

1Push root (1) onto stack
1push23
1/5

Code

This approach works well, but we're not doing a "true" postorder traversal. We collect everything and reverse at the end.

Can we visit nodes in genuine postorder using a stack, without any reversal?

Approach 3: Iterative with Single Stack (True Postorder)

Intuition

This approach truly mimics what the recursion does, without the reversal trick. The challenge is clear: when we're at a node, we need to process its left subtree, then its right subtree, and only then process the node itself. With a stack, we naturally encounter the node before its children. So we need a way to "skip" processing a node until both its children are done.

The trick is to track the previously processed node. When we look at the top of the stack, we ask: have we already processed this node's right child? If the right child is null or equals the previously processed node, we know the right subtree is done, so it's safe to process the current node. Otherwise, we need to go right first.

Algorithm

  1. If the root is null, return an empty list.
  2. Create a stack and set current = root. Initialize previous = null.
  3. While current is not null or the stack is not empty:
    • While current is not null, push current onto the stack and move to current.left.
    • Peek at the top of the stack.
    • If the top node's right child is null or equals previous (right subtree is done):
      • Pop the node, add its value to the result, set previous = node.
    • Otherwise, move to the right child: current = top.right.
  4. Return the result.

Example Walkthrough

1Push left chain: push 3, push 1. Stack: [3, 1]
3stack1peek2
1/5

Code