Iteration vs Recursion
📖 Concept
Every recursive solution can be converted to an iterative one and vice versa. Choosing between them involves tradeoffs in readability, performance, and stack safety.
Iteration: Uses loops (for, while). Runs in O(1) extra space (no stack frames). Best for simple repetitive tasks.
Recursion: Function calls itself. Uses O(n) stack space (one frame per call). Best for problems with recursive structure (trees, graphs, divide & conquer).
When to use each:
| Criteria | Iteration | Recursion |
|---|---|---|
| Stack space | O(1) | O(n) stack frames |
| Readability | Better for simple loops | Better for tree/graph/divide problems |
| Performance | Slight edge (no function call overhead) | Function call overhead per frame |
| Stack overflow risk | None | Yes, for deep recursion |
| Natural fit | Arrays, counting, accumulating | Trees, graphs, backtracking, D&C |
Converting recursion to iteration: The universal technique is using an explicit stack (or queue) to simulate the call stack:
- Replace function calls with pushing to a stack
- Replace returns with popping from the stack
- Replace parameters with data in the stack
Tail recursion: A special form where the recursive call is the LAST operation. Some engines can optimize this to use O(1) space (tail call optimization / TCO). JavaScript supports TCO in strict mode in Safari only.
🏠 Real-world analogy: Iteration is like walking up stairs one step at a time. Recursion is like giving instructions: "Go up one step, then follow these same instructions." Both reach the top, but recursion requires remembering where you are at each step (stack frames).
💻 Code Example
1// FACTORIAL — Both ways2// Recursive: O(n) time, O(n) space3function factorialRecursive(n) {4 if (n <= 1) return 1;5 return n * factorialRecursive(n - 1);6}78// Iterative: O(n) time, O(1) space ✅9function factorialIterative(n) {10 let result = 1;11 for (let i = 2; i <= n; i++) {12 result *= i;13 }14 return result;15}1617// FIBONACCI — Both ways18// Recursive: O(2ⁿ) time, O(n) space 💀19function fibRecursive(n) {20 if (n <= 1) return n;21 return fibRecursive(n - 1) + fibRecursive(n - 2);22}2324// Iterative: O(n) time, O(1) space ✅25function fibIterative(n) {26 if (n <= 1) return n;27 let prev = 0, curr = 1;28 for (let i = 2; i <= n; i++) {29 [prev, curr] = [curr, prev + curr];30 }31 return curr;32}3334// TREE TRAVERSAL — Recursion is natural, but can be iterative35// Recursive DFS36function inorderRecursive(node, result = []) {37 if (!node) return result;38 inorderRecursive(node.left, result);39 result.push(node.val);40 inorderRecursive(node.right, result);41 return result;42}4344// Iterative DFS with explicit stack45function inorderIterative(root) {46 const result = [];47 const stack = [];48 let current = root;49 while (current || stack.length) {50 while (current) {51 stack.push(current);52 current = current.left;53 }54 current = stack.pop();55 result.push(current.val);56 current = current.right;57 }58 return result;59}6061// TAIL RECURSION — O(1) space if engine supports TCO62function factorialTail(n: number, acc: number = 1): number {63 if (n <= 1) return acc;64 return factorialTail(n - 1, n * acc); // Tail position!65}66// The recursive call is the LAST thing — no work after it67// Compiler can reuse the same stack frame (TCO)6869// CONVERTING RECURSION TO ITERATION — General pattern70// Recursive:71function sumRecursive(arr, i = 0) {72 if (i >= arr.length) return 0;73 return arr[i] + sumRecursive(arr, i + 1);74}7576// Converted to iterative:77function sumIterative(arr) {78 let total = 0;79 for (let i = 0; i < arr.length; i++) {80 total += arr[i];81 }82 return total;83}
🏋️ Practice Exercise
Practice Problems:
- Convert recursive fibonacci to iterative — compare speed for fib(40)
- Convert recursive binary search to iterative
- Write both recursive and iterative versions of array reversal
- Convert recursive tree traversal (preorder) to iterative using a stack
- Write a recursive function to print numbers 1 to n, then convert to iterative
- Implement GCD using both recursion and iteration
- Convert a recursive string reversal to iterative
- Write tail-recursive versions of: sum, factorial, fibonacci
- When would you PREFER recursion over iteration despite the stack overhead?
- Measure the maximum n for recursive factorial before stack overflow in your runtime
⚠️ Common Mistakes
Always using recursion because it 'looks elegant' — for simple problems, iteration is clearer and more efficient
Not realizing iterative tree traversal needs an explicit stack — you replace the implicit call stack with your own
Thinking tail call optimization works everywhere — only Safari supports TCO in JavaScript; Node.js does NOT
Converting recursion to iteration incorrectly — the explicit stack must mirror the call stack's behavior exactly
Assuming recursion is always slower — for tree/graph problems, recursive code often runs at the same speed
💼 Interview Questions
🎤 Mock Interview
Practice a live interview for Iteration vs Recursion