Compose & Trace Recursive Algorithms (HL)
What Are Recursive Algorithms?
Recursion occurs when a function calls itself to solve a smaller version of a problem.
Every recursive algorithm needs a base case to stop further calls and avoid infinite loops.
How Recursive Algorithms Work
Each recursive function follows two parts:
- Base Case: The simplest instance that returns a direct result (e.g.
n == 0). - Recursive Case: The function calls itself with a smaller or simpler argument.
Example: Recursive Factorial Function
def factorial(n):
if n == 0:
return 1 # Base case
return n * factorial(n - 1) # Recursive case
print("Factorial:", factorial(5))
public class RecursionExample {
public static int factorial(int n) {
if (n == 0) return 1; // Base case
return n * factorial(n - 1); // Recursive case
}
public static void main(String[] args) {
System.out.println("Factorial: " + factorial(5));
}
}
Tracing factorial(5)
How to Trace factorial(5)
- Recall the rule:
factorial(n) = n × factorial(n−1)with base casefactorial(1) = 1(orfactorial(0) = 1). - Walk down the calls: record each call
factorial(5)→factorial(4)→factorial(3)→factorial(2)→factorial(1). - At the base case, return
1. - Walk up the stack: for each waiting call, compute
n × (return from below)and record that value. - Continue until the original call returns
120.
| Step | Action | n | Return Value |
|---|---|---|---|
| 1 | Call factorial(5) |
5 | |
| 2 | Call factorial(4) |
4 | |
| 3 | Call factorial(3) |
3 | |
| 4 | Call factorial(2) |
2 | |
| 5 | Call factorial(1) |
1 | |
| 6 | Call factorial(0) (base case) |
0 | 1 |
| 7 | Return from factorial(1): 1 × 1 |
1 | 1 |
| 8 | Return from factorial(2): 2 × 1 |
2 | 2 |
| 9 | Return from factorial(3): 3 × 2 |
3 | 6 |
| 10 | Return from factorial(4): 4 × 6 |
4 | 24 |
| 11 | Return from factorial(5): 5 × 24 |
5 | 120 |
Example: Sum of N Natural Numbers
def sum_n(n):
if n == 0:
return 0 # Base case
return n + sum_n(n - 1) # Recursive case
print("Sum:", sum_n(5))
public class RecursiveSum {
public static int sumN(int n) {
if (n == 0) return 0; // Base case
return n + sumN(n - 1); // Recursive case
}
public static void main(String[] args) {
System.out.println("Sum: " + sumN(5));
}
}
Tracing sum_n(5)
How to Trace sum_n(5)
- Recall the rule:
sum_n(n) = n + sum_n(n−1)with base casesum_n(0) = 0(orsum_n(1) = 1). - Walk down the calls:
sum_n(5)→sum_n(4)→sum_n(3)→sum_n(2)→sum_n(1)→ base. - At the base, return
0. - Walk up the stack: at each level compute
n + (return from below)and update “Accumulated Sum” (e.g.0 → 1 → 3 → 6 → 10 → 15). - The original call returns
15.
| Step | Call | n |
Return | Accumulated Sum |
|---|---|---|---|---|
| 1 | sum_n(5) | 5 | ||
| 2 | sum_n(4) | 4 | ||
| 3 | sum_n(3) | 3 | ||
| 4 | sum_n(2) | 2 | ||
| 5 | sum_n(1) | 1 | ||
| 6 | sum_n(0) | 0 | 0 | 0 |
| 7 | return from sum_n(1) | 1 | 1 + 0 = 1 | 1 |
| 8 | return from sum_n(2) | 2 | 2 + 1 = 3 | 3 |
| 9 | return from sum_n(3) | 3 | 3 + 3 = 6 | 6 |
| 10 | return from sum_n(4) | 4 | 4 + 6 = 10 | 10 |
| 11 | return from sum_n(5) | 5 | 5 + 10 = 15 | 15 |
Avoiding Common Errors
- Missing Base Case: Always define and test the simplest case (eg
n == 0), or risk infinite recursion. - Excessive Calls: Cache results when possible (memoisation) to avoid redundant work.
- Stack Overflow: Keep recursion depth reasonable or convert to iterative solutions when you hit limits.
Key Takeaways
- Recursive algorithms call themselves on a smaller input until a base case is reached.
- Tracing helps visualise the call stack and return values step by step.
- Simple recursive patterns include factorial and sum of natural numbers.
- Recursion can simplify code but requires care to avoid memory and performance issues.