The Stacks
UNIT 4: DATA COLLECTIONS · TOPIC 4.16

4.16 Recursion

A method that calls itself. On the revised exam you trace recursion — you don't write it. Know the base case, count the calls, and follow the returns back up.

What you need to know

  • A recursive method calls itself. It needs a base case (a condition where it returns without recursing) and a recursive call that moves toward the base case.
  • Without a reachable base case, recursion never ends — a run-time stack overflow.
  • Each call has its own copies of parameters and local variables. Changes in one call don't affect the others.
  • Tracing: write each call with its argument, stop at the base case, then substitute return values back up the chain. Or draw the calls as a stack.
  • Number of calls is a common question: count every invocation including the original.
  • Any recursive method can be rewritten with a loop, and vice versa; recursion often mirrors the structure of the problem (factorial, sum of a list, string reversal).
  • The revised CED says you will trace recursive code, not write it — FRQs won't require recursion.

Worked example

public static int f(int n)
{
    if (n <= 1) return 1;          // base case
    return n * f(n - 1);           // recursive call
}
// f(4) = 4 * f(3)
//      = 4 * (3 * f(2))
//      = 4 * (3 * (2 * f(1)))
//      = 4 * (3 * (2 * 1)) = 24
// Calls made: f(4), f(3), f(2), f(1) → 4 calls

public static void printDown(int n)
{
    if (n == 0) return;
    System.out.print(n + " ");
    printDown(n - 1);
}
// printDown(3) prints: 3 2 1

Trace it yourself

Step through with the buttons, or use the ← → keys. Changed variables are highlighted.

Exam tip: Write the calls in a column, arguments decreasing, until the base case returns a concrete value. Then fill in upward. For methods that print, note whether the print happens before or after the recursive call — that reverses the order of output.

Going deeper

The nuance, edge cases, and connections that turn a 3 into a 5.

  • Structure: base case(s) first (return without recursing), then recursive case(s) (call with a smaller/closer argument, combine the result). If the argument doesn't get closer to a base case, infinite recursion → StackOverflowError.
  • Each call has its own frame: its own parameters and locals. When f(4) calls f(3), f(4)'s n is still 4; f(3)'s n is 3. Changes in the inner call don't affect the outer.
  • Two tracing techniques. Substitution: expand f(4) = 4 * f(3) = 4 * 3 * f(2) … until base, then multiply back. Stack: list the calls in a column as they happen; when the base returns, cross off from the bottom up, writing each return value.
  • Order of side effects: a print before the recursive call happens on the way down (n, n−1, …). A print after happens on the way up (…, n−1, n). Same code, reversed output.
  • Counting calls: include the original. f(n) with f(n−1) makes n calls to reach f(1)… or n+1 to reach f(0). Halving (f(n/2)) makes about log₂ n + 1 calls.
  • Base case correctness: the recursion must hit it exactly. if (n == 0) with f(n - 2) from an odd n skips 0 and never stops. if (n <= 0) is the safe form.
  • Recursion on Strings and arrays: process the first character, recurse on the rest (s.substring(1)); or use an index parameter that increments. Base case: empty string / index == length.
  • Any loop can be recursion and vice versa. The exam may show a recursive method and ask which loop is equivalent.
  • The 2025–26 CED says recursion is traced, not written. FRQs won't require it. Multiple choice will trace it.

Mistakes that cost points

  • Not tracking each frame's own variables. Inner calls don't change outer variables.
  • Printing in the wrong order. Before the call = descending. After = ascending.
  • Miscounting calls. Include the first call and the base-case call.
  • Missing a skipped base case. Check whether the argument sequence actually hits it.

Practice questions

Written in the style of the real exam. Try each one before revealing the answer.

Q1 What is returned by g(5)?
public static int g(int n)
{
    if (n == 0) return 0;
    return n + g(n - 2);
}
  1. A 9
  2. B 15
  3. C 5
  4. D The method never terminates
Show answer

Answer: D. g(5) calls g(3), which calls g(1), which calls g(-1). The base case checks n == 0 exactly, and n goes 5, 3, 1, -1, -3, … skipping 0 entirely. The base case is never reached, so the recursion never stops. (A base case of n <= 0 would fix it and return 9.)

Q2 What is printed by p(3)?
public static void p(int n)
{
    if (n > 0)
    {
        p(n - 1);
        System.out.print(n + " ");
    }
}
  1. A 3 2 1
  2. B 1 2 3
  3. C 3 2 1 0
  4. D 0 1 2 3
Show answer

Answer: B. The print happens after the recursive call, so the deepest call prints first: 1, then 2, then 3.

Q3 How many times is the method h called (including the initial call) when h(8) is executed?
public static int h(int n)
{
    if (n < 1) return 0;
    return 1 + h(n / 2);
}
  1. A 3
  2. B 4
  3. C 5
  4. D 8
Show answer

Answer: C. h(8) → h(4) → h(2) → h(1) → h(0). Five calls.

Key vocabulary

Recursion
a method calling itself
Base case
the condition under which a recursive method returns without recursing
Recursive call
the call to the same method with an argument closer to the base case