Binary TreesProblem 6 of 35
Inorder Traversal of a tree both using recursion and Iteration
Problem Statement
Given a binary tree, perform inorder traversal (Left -> Root -> Right) and return the list of node values. Implement both recursive and iterative approaches.
Example:
1
/ \
2 3
/ \
4 5
- Input: Root of the above tree
- Output:
[4, 2, 5, 1, 3]
Approach 1: Recursive (Simple DFS)
Intuition
Follow the inorder pattern: traverse left subtree, visit root, traverse right subtree.
Algorithm
- Recursively traverse left subtree
- Process/visit the current node
- Recursively traverse right subtree
java
import java.util.*;
class TreeNode {
int val;
TreeNode left, right;
TreeNode(int x) { val = x; }
}
public class Solution {
public void inorderRecursive(TreeNode root, List<Integer> result) {
if (root == null) return;
inorderRecursive(root.left, result); // Left
result.add(root.val); // Root
inorderRecursive(root.right, result); // Right
}
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<>();
inorderRecursive(root, result);
return result;
}
}Complexity Analysis
- Time Complexity: O(n) - Visit each node once
- Space Complexity: O(n) - Recursion stack for skewed tree
Approach 2: Iterative (Using Stack)
Intuition
Use an explicit stack to simulate the recursion. Go as left as possible, then process node, then go right.
Algorithm
- Initialize an empty stack
- Go to the leftmost node, pushing all nodes onto stack
- Pop a node, process it, then go to its right subtree
- Repeat until stack is empty and current is null
java
import java.util.*;
class TreeNode {
int val;
TreeNode left, right;
TreeNode(int x) { val = x; }
}
public class Solution {
public List<Integer> inorderIterative(TreeNode root) {
List<Integer> result = new ArrayList<>();
Stack<TreeNode> stack = new Stack<>();
TreeNode current = root;
while (current != null || !stack.isEmpty()) {
// Go to the leftmost node
while (current != null) {
stack.push(current);
current = current.left;
}
// Process the node
current = stack.pop();
result.add(current.val);
// Go to right subtree
current = current.right;
}
return result;
}
}Complexity Analysis
- Time Complexity: O(n) - Visit each node once
- Space Complexity: O(n) - Stack can hold all nodes in worst case
Approach 3: Optimal (Morris Traversal - No Extra Space)
Intuition
Use threaded binary tree concept. Create temporary links (threads) to traverse without stack. Find inorder predecessor and create a link to current node.
Algorithm
- If left child is null, process node and go right
- If left child exists, find inorder predecessor (rightmost in left subtree)
- If predecessor's right is null, create thread and go left
- If predecessor's right points to current, remove thread, process node, go right
java
import java.util.*;
class TreeNode {
int val;
TreeNode left, right;
TreeNode(int x) { val = x; }
}
public class Solution {
public List<Integer> inorderMorris(TreeNode root) {
List<Integer> result = new ArrayList<>();
TreeNode current = root;
while (current != null) {
if (current.left == null) {
// No left subtree, process current and go right
result.add(current.val);
current = current.right;
} else {
// Find inorder predecessor
TreeNode predecessor = current.left;
while (predecessor.right != null &&
predecessor.right != current) {
predecessor = predecessor.right;
}
if (predecessor.right == null) {
// Create thread
predecessor.right = current;
current = current.left;
} else {
// Thread exists, remove it and process current
predecessor.right = null;
result.add(current.val);
current = current.right;
}
}
}
return result;
}
}Complexity Analysis
- Time Complexity: O(n) - Each edge is traversed at most twice
- Space Complexity: O(1) - No extra space used (modifies tree temporarily)
Key Takeaways
- Inorder = Left -> Root -> Right (gives sorted order for BST)
- Recursive approach is simple but uses O(n) stack space
- Iterative approach uses explicit stack, easier to control
- Morris Traversal achieves O(1) space by using threads
- Morris traversal temporarily modifies the tree but restores it