Problem
Given a binary tree, write a non recursive or iterative algorithm for Inorder traversal.
Inorder Traversal
- First, visit all the nodes in the left subtree
- Then the root node
- Visit all the nodes in the right subtree
inorder(root->left)
display(root->data)
inorder(root->right)
Example
Example 1:
1
\
2
/
3
Input: root = [1,null,2,3]
Output: [1,3,2]
Example 2:
graph TD; 1 --- 2 & 3 2 --- 4 & 5 3 --- 6 & 7
Input: root = [1,2,3,4,5, 6, 7]
Output: [4, 2, 5, 1, 6, 3, 7]
Follow up
Using recursion is not allowed.
There are 3 solutions for solving this problem.
Solution
This is how the inorder traversal looks:
Method 1 - Recursive
The recursive solution is trivial.
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> ans = new ArrayList<>();
if (root == null) {
return ans;
}
helper(root, ans);
}
private void helper(TreeNode root, List<Integer> ans) {
if (root == null) {
return;
}
helper(root.left, ans);
ans.add(root.val);
helper(root.right, ans);
}
Complexity
- ⏰ Time complexity:
O(n)
, as each node is visited once. - 🧺 Space complexity:
O(n)
(using recursive stack)
Method 2 - Iterative Approach - Morris Traversal
Complexity
- ⏰ Time complexity:
O(n)
, as each node is visited once. - 🧺 Space complexity:
O(1)
Method 3 - Iterative Using Stack
The key to solve inorder traversal of binary tree includes the following:
- The order of “inorder” is: left child -> parent -> right child
- Use a stack to track nodes
- Understand when to push node into the stack and when to pop node out of the stack
Here is the pushing order of nodes in stack:
Dry Run
Code
Java
public ArrayList < Integer > inorderTraversal(TreeNode root) {
List<Integer> ans = new ArrayList<> ();
if (root == null) {
return list;
}
Stack<TreeNode> stack = new Stack <>();
TreeNode curr = root;
while (!stack.isEmpty() || curr != null) {
if (curr != null) {
stack.push(curr);
curr = curr.left;
} else {
TreeNode t = stack.pop();
ans.add(t.val);
curr = t.right;
}
}
return ans;
}
We can also write code like this:
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> ans = new LinkedList<Integer>();
if (root == null) {
return ans;
}
Stack<TreeNode> stack = new Stack<TreeNode>();
TreeNode cur = root;
while (cur != null || !stack.isEmpty()) {
while (cur != null) {// Travel to each node's left child, till reach the left leaf
stack.push(cur);
cur = cur.left;
}
cur = stack.pop(); // Backtrack to higher level node A
ans.add(cur.val); // Add the node to the result list
cur = cur.right; // Switch to A'right branch
}
return ans;
}
Complexity
- ⏰ Time complexity:
O(n)
, as each node is visited once. - 🧺 Space complexity:
O(n)
Method 4 - Using Stack with Tree Modification
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> ans = new ArrayList<Integer>();
if (root == null) {
return ans;
}
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()) {
TreeNode top = stack.peek();
if (top.left != null) {
stack.push(top.left);
top.left = null; // modifying the tree
} else {
ans.add(top.val);
stack.pop();
if (top.right != null) {
stack.push(top.right);
}
}
}
return ans;
}