Skip to content

Recursion vs Iteration

Both recursion and iteration solve repetitive problems, but they differ in clarity, efficiency, and use cases. Understanding trade-offs helps you choose correctly.

Mental Model

Recursion uses the call stack as implicit state; iteration uses explicit variables. Recursion is often clearer for problems with natural self-similar structure (trees, nested data), while iteration is more memory-efficient and avoids Python's recursion limit. When in doubt, write it recursively for clarity, then convert to iteration if performance demands it.


Sum Calculation: Both Approaches

```python

Recursive: Natural for mathematical definitions

def sum_recursive(numbers): if not numbers: return 0 return numbers[0] + sum_recursive(numbers[1:])

Iterative: More memory-efficient

def sum_iterative(numbers): total = 0 for num in numbers: total += num return total

numbers = [1, 2, 3, 4, 5] print(sum_recursive(numbers)) # 15 print(sum_iterative(numbers)) # 15 ```

Factorial Comparison

```python

Recursive: Elegant, matches mathematical notation

def factorial_recursive(n): if n <= 1: return 1 return n * factorial_recursive(n - 1)

Iterative: More predictable performance

def factorial_iterative(n): result = 1 for i in range(2, n + 1): result *= i return result

print(factorial_recursive(5)) # 120 print(factorial_iterative(5)) # 120 ```

Tree Traversal: Recursion's Strength

```python class Node: def init(self, value): self.value = value self.children = []

Recursive: Simple and clear

def count_nodes_recursive(node): count = 1 for child in node.children: count += count_nodes_recursive(child) return count

Iterative: Requires stack data structure

def count_nodes_iterative(root): count = 0 stack = [root] while stack: node = stack.pop() count += 1 stack.extend(node.children) return count ```

Performance and Memory

```python import sys

Check stack depth limit

print(f"Recursion limit: {sys.getrecursionlimit()}")

Iterative uses constant stack space

Recursive uses O(n) stack space

For large n, iteration is safer

def large_sum_iterative(n): return sum(range(n))

def large_sum_recursive(n): if n <= 0: return 0 return n + large_sum_recursive(n - 1) ```

When to Use Each

Use Recursion for:

  • Tree/graph traversal
  • Divide-and-conquer algorithms
  • Mathematical problem definitions
  • When code clarity is priority

Use Iteration for:

  • Simple loops (for, while)
  • Processing sequences
  • When memory/stack is limited
  • Performance-critical code

Exercises

Exercise 1. Write both recursive and iterative versions of a function count_digits(n) that returns the number of digits in a positive integer. Compare both on the input 123456789.

Solution to Exercise 1
# Recursive
def count_digits_recursive(n):
    if n < 10:
        return 1
    return 1 + count_digits_recursive(n // 10)

# Iterative
def count_digits_iterative(n):
    count = 0
    while n > 0:
        count += 1
        n //= 10
    return count

print(count_digits_recursive(123456789))  # 9
print(count_digits_iterative(123456789))  # 9

Exercise 2. Implement both recursive and iterative versions of fibonacci(n). Time both for n = 30 and n = 35 and compare performance. Explain why the recursive version is dramatically slower.

Solution to Exercise 2
import time

# Recursive (exponential time)
def fib_recursive(n):
    if n < 2:
        return n
    return fib_recursive(n - 1) + fib_recursive(n - 2)

# Iterative (linear time)
def fib_iterative(n):
    if n < 2:
        return n
    a, b = 0, 1
    for _ in range(n - 1):
        a, b = b, a + b
    return b

for n in [30, 35]:
    start = time.time()
    r = fib_recursive(n)
    t_rec = time.time() - start

    start = time.time()
    i = fib_iterative(n)
    t_iter = time.time() - start

    print(f"n={n}: recursive={t_rec:.3f}s, iterative={t_iter:.6f}s")
# Recursive is exponential O(2^n); iterative is O(n).

Exercise 3. Write a recursive tree_depth(node) function that returns the maximum depth of a binary tree (where each node has .left and .right attributes). Then write an iterative version using a stack. Build a sample tree and verify both return the same result.

Solution to Exercise 3
class TreeNode:
    def __init__(self, val, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

# Recursive
def tree_depth_recursive(node):
    if node is None:
        return 0
    return 1 + max(tree_depth_recursive(node.left),
                   tree_depth_recursive(node.right))

# Iterative (using stack with depth tracking)
def tree_depth_iterative(root):
    if root is None:
        return 0
    max_depth = 0
    stack = [(root, 1)]
    while stack:
        node, depth = stack.pop()
        max_depth = max(max_depth, depth)
        if node.left:
            stack.append((node.left, depth + 1))
        if node.right:
            stack.append((node.right, depth + 1))
    return max_depth

root = TreeNode(1,
    TreeNode(2, TreeNode(4), TreeNode(5)),
    TreeNode(3, None, TreeNode(6, TreeNode(7), None)),
)

print(tree_depth_recursive(root))  # 4
print(tree_depth_iterative(root))  # 4