Skip to content
dsa450for five year olds

Binary Trees · 6 of 35

Inorder Traversal of a tree both using recursion and Iteration

Visit every node of a tree as left side, then me, then right side, first with a helper that calls itself and then with your own pile of bookmarks.

Simple way
time O(n)
room O(h)
Clever way
time O(n)
room O(h)

The problem, simply

You get a binary tree. Write down every value in this order: first everything in the left side, then the node itself, then everything in the right side. Do the same inside each side. This order is called inorder.

You must do it two ways: with a function that calls itself, and with a loop and your own stack.

A story to remember it

Picture it

tree
1234564th2nd5th1st3rd6th

Each node has a number under it that says when inorder reads it. 4 comes first because it is the leftmost person. 1 comes after its whole left family.

Examples

A normal tree

In
[1, 2, 3, 4, 5, null, 6]
Out
[4, 2, 5, 1, 3, 6]

Left family of 1 is 4, 2, 5. Then 1. Then the right family, 3, 6.

A search tree comes out sorted

In
[4, 2, 6, 1, 3, 5, 7]
Out
[1, 2, 3, 4, 5, 6, 7]

In a binary search tree every left side is smaller and every right side is bigger, so inorder reads it from small to big. This is the most used fact about inorder.

A stick leaning left

In
[3, 2, null, 1]
Out
[1, 2, 3]

You slide all the way down before reading anything, so the bottom node comes first. The stack gets as tall as the tree here.

No tree

In
[]
Out
[]

Return an empty list.

Way 1: the simple way

Write a helper that reads one node: first it reads the left side with itself, then writes the node, then reads the right side with itself. An empty node does nothing.

  1. If the node is empty, return.
  2. Read the left side.
  3. Write the node's value.
  4. Read the right side.
tree
123456
stackhelpers waiting
read(1)read(2)read(4)top

While 4 is being written, the helpers for 1 and 2 are still waiting on the call stack.

  • looking now
  • seen
  • path
java
import java.util.*;

class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> out = new ArrayList<>();
        read(root, out);
        return out;
    }

    private void read(TreeNode node, List<Integer> out) {
        if (node == null) return;
        read(node.left, out);     // left family first
        out.add(node.val);        // then me
        read(node.right, out);    // then right family
    }
}

How long it takes: each node is written once, O(n). Extra room: the waiting helpers form a pile as tall as the tree, O(h). That is O(n) for a stick.

Way 2: the clever way

Do the same thing with your own pile of bookmarks, a stack. You control it, so a very deep tree cannot crash your program the way deep recursion can, and interviewers love to see it.

  1. Start with curr at the root.
  2. While curr is not empty, push it on the stack and move curr to its left child. This slides down the left edge.
  3. When curr is empty, pop the top bookmark. Write its value.
  4. Move curr to that node's right child and go back to step 2.
  5. Stop when curr is empty and the stack is empty.

Slide left, pop, write, go right

01 / 11

tree
123456curr
arrayanswer
stackstack
empty

Start with curr on the root, 1. The stack is empty.

  • looking now
  • seen
  • done
  • answer
  • just added
java
import java.util.*;

class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> out = new ArrayList<>();
        Deque<TreeNode> stack = new ArrayDeque<>();
        TreeNode curr = root;
        while (curr != null || !stack.isEmpty()) {
            while (curr != null) {          // slide down the left edge
                stack.push(curr);           // leave a bookmark
                curr = curr.left;
            }
            curr = stack.pop();             // nearest bookmark
            out.add(curr.val);              // write it
            curr = curr.right;              // then its right family
        }
        return out;
    }
}

How long it takes: every node is pushed once and popped once, O(n). Extra room: the stack holds one bookmark per floor on the current way down, O(h).

Way 3: no stack at all (Morris)

Can you do it with O(1) extra room? Yes, by borrowing empty arrows in the tree. Before going into a left family, find the last person that family would write (go left once, then right as far as you can). That person's right arrow is empty. Tie a ribbon from it back to the current node. Later, when the walk follows that ribbon, you know the left family is finished: untie it, write the node, and go right.

Ribbons replace the stack

01 / 08

tree
123456ribbon to 1curr
arrayanswer

1 has a left side. Find the last node you would write before 1: that is 5. Tie a ribbon from 5 back to 1, then go left.

  • checking
  • seen
  • done
  • just added
java
import java.util.*;

class Solution {
    public List<Integer> inorderMorris(TreeNode root) {
        List<Integer> out = new ArrayList<>();
        TreeNode curr = root;
        while (curr != null) {
            if (curr.left == null) {
                out.add(curr.val);              // nothing on the left: write me
                curr = curr.right;              // may follow a ribbon up
            } else {
                TreeNode pre = curr.left;       // last one written before me
                while (pre.right != null && pre.right != curr) pre = pre.right;
                if (pre.right == null) {
                    pre.right = curr;           // tie the ribbon
                    curr = curr.left;
                } else {
                    pre.right = null;           // untie it, the left side is done
                    out.add(curr.val);
                    curr = curr.right;
                }
            }
        }
        return out;
    }
}

Each arrow is walked at most a few times, so it is still O(n) time, with O(1) extra room. The tree is changed during the walk and put back by the end, so it is not safe if another thread reads the tree at the same time.

Watch out for

  • Pushing children like in preorder (right, then left) does not give inorder. Inorder needs the "slide left" inner loop.
  • An empty tree. The loop never runs and you return an empty list, which is correct.
  • In Morris, forgetting to untie the ribbon leaves a loop in the tree.

What interviewers ask next

  • Check if a tree is a valid binary search tree. Do an inorder walk and make sure every value is bigger than the one before.
  • Find the k-th smallest value in a search tree. Do the iterative inorder walk and stop at the k-th pop.
  • Build a search tree iterator with next() and hasNext(). Keep the stack between calls: next() pops one node and slides left from its right child. Each call is O(1) on average and memory is O(h).
  • Recover a search tree where two values were swapped. Inorder finds the two places where the order goes down.

Remember this

Grown-up words: the bookmarks are a stack, the helper that calls itself is recursion, the waiting helpers are the call stack, the ribbons are threads (Morris traversal uses a threaded binary tree), and the last person in a left family is the inorder predecessor.