PrepGo

Recursion - AP Computer Science A Study Guide

Written by AP Content Team, Verified for 2026 AP Exams, Last updated: May 2026

Learn with study guides reviewed by top AP teachers. This guide takes about 10 minutes to read.

Getting Started

In programming, we often use loops to repeat a task. However, some problems can be solved more elegantly by breaking them down into smaller, self-similar subproblems. Recursion is a powerful programming technique where a method solves a problem by calling itself with a simpler version of the same problem, providing a concise and often more readable alternative to complex iteration.

What You Should Be Able to Do

  • Define recursion and identify its two essential components in a method.

  • Trace the execution of a recursive method, showing how the call stack manages each call.

  • Write a simple recursive method that includes a base case and a recursive step.

  • Explain how infinite recursion leads to a StackOverflowError.

Key Concepts & Java Implementation

The Core Idea

Recursion is a process where a method calls itself to solve a problem. Think of it like a set of Russian nesting dolls: to open the whole set, you open the largest doll, which contains a slightly smaller, identical doll. You repeat this process until you reach the smallest doll that cannot be opened.

This analogy highlights the two critical parts of any correct recursive solution:

  1. Base Case: This is the simplest possible version of the problem, which can be solved directly without making another recursive call. It is the condition that stops the recursion. In the doll analogy, it's the smallest, solid doll.

  2. Recursive Step (or Recursive Call): This is where the method calls itself, but with a modified argument that moves the problem closer to the base case. It breaks the current problem down into a smaller, simpler piece. In the analogy, it's the act of opening one doll to find the next smaller one inside.

Without a base case, a recursive method would call itself forever, a condition known as infinite recursion.

Syntax & Implementation

Recursion does not use new keywords; it is a structural pattern. A recursive method typically uses an if-else statement to differentiate between the base case and the recursive step.

General Structure of a Recursive Method:


public returnType recursiveMethod(parameters) {

    // 1. Base Case: The condition that stops the recursion.

    if (/* this is the simplest case */) {

        return /* a direct, non-recursive answer */;

    } 

    // 2. Recursive Step: The method calls itself with a "smaller" problem.

    else {

        return /* calculation involving a call to recursiveMethod(modified_parameters) */;

    }

}

Annotated Java Examples

Example 1: A Simple Countdown

This method prints numbers from n down to 1. The problem gets "smaller" as n decreases with each call.


public class Counter {

    /**

     * Prints numbers from n down to 1.

     * @param n The starting number (must be positive).

     */

    public void countDown(int n) {

        // Base Case: If n is zero or less, stop the recursion.

        if (n <= 0) {

            System.out.println("Go!");

            return; // Exit the method.

        } 

        // Recursive Step: Print the current number, then call itself with n-1.

        else {

            System.out.println(n);

            countDown(n - 1); // The problem size is reduced by 1.

        }

    }

}

Example 2: Calculating a Factorial

The factorial of a non-negative integer n, denoted n!, is the product of all positive integers up to n. For example, 4! = 4 * 3 * 2 * 1 = 24. The base case is 0! = 1.


public class MathUtils {

    /**

     * Calculates the factorial of a non-negative integer n.

     * @param n The number to calculate the factorial of.

     * @return The value of n!

     */

    public int factorial(int n) {

        // Base Case: The factorial of 0 is 1. This stops the recursion.

        if (n == 0) {

            return 1;

        } 

        // Recursive Step: n! = n * (n-1)!

        else {

            // The result is n multiplied by the result of the smaller subproblem.

            return n * factorial(n - 1); 

        }

    }

}

Tracing & Analysis

Execution Trace

To understand recursion, we must trace how Java handles the method calls. Each time a method is called, it gets its own set of local variables and is pushed onto the call stack. When a method finishes, it is popped off the stack.

Let's trace the execution of factorial(3):

  1. main calls factorial(3).

    • n is 3. Is n == 0? No.

    • It must compute 3 * factorial(2). It pauses and calls factorial(2).

    • Call Stack:main -> factorial(3)

  2. factorial(3) calls factorial(2).

    • n is 2. Is n == 0? No.

    • It must compute 2 * factorial(1). It pauses and calls factorial(1).

    • Call Stack:main -> factorial(3) -> factorial(2)

  3. factorial(2) calls factorial(1).

    • n is 1. Is n == 0? No.

    • It must compute 1 * factorial(0). It pauses and calls factorial(0).

    • Call Stack:main -> factorial(3) -> factorial(2) -> factorial(1)

  4. factorial(1) calls factorial(0).

    • n is 0. Is n == 0? Yes.

    • This is the base case. It returns 1. The factorial(0) call is finished and popped off the stack.

    • Call Stack:main -> factorial(3) -> factorial(2) -> factorial(1)

  5. Control returns to factorial(1).

    • It can now complete its calculation: 1 * factorial(0) becomes 1 * 1.

    • It returns 1. The factorial(1) call is finished.

    • Call Stack:main -> factorial(3) -> factorial(2)

  6. Control returns to factorial(2).

    • It can now complete its calculation: 2 * factorial(1) becomes 2 * 1.

    • It returns 2. The factorial(2) call is finished.

    • Call Stack:main -> factorial(3)

  7. Control returns to factorial(3).

    • It can now complete its calculation: 3 * factorial(2) becomes 3 * 2.

    • It returns 6. The factorial(3) call is finished.

    • Call Stack:main

The final result, 6, is returned to the main method.

Analysis

If a recursive method lacks a base case, or if the recursive step never reaches the base case, it will call itself indefinitely. Each method call consumes memory on the call stack. Eventually, the call stack runs out of space, and the Java Virtual Machine throws a StackOverflowError, crashing the program.

Java Syntax Quick-Reference

Recursion is a pattern, not a specific keyword. The key components are:

  • methodName(args): A standard method call. In recursion, this call is made to the same method that is currently executing.

  • if (condition): Used to check for the base case, which stops the recursive process.

  • return: Crucial for sending a value back from a completed method call to the caller, allowing the chain of calls to "unwind" and compute a final result.

Core Code Examples & Terminology

  • Recursion: A problem-solving technique where a method calls itself to solve smaller, identical versions of the problem.

  • Base Case: The condition within a recursive method that stops further recursive calls by providing a direct solution to the simplest version of the problem.

  • Recursive Step: The part of a recursive method that calls itself, passing arguments that move the problem closer to the base case.

  • StackOverflowError: A runtime error that occurs when a program's call stack runs out of memory, typically caused by infinite recursion.

  • Core Snippet 1: General Recursive Structure:

    
    public int solve(int param) {
    
        if (param == /* base case value */) {
    
            return /* simple answer */;
    
        } else {
    
            return /* expression involving solve(param - 1) or similar */;
    
        }
    
    }
    

    This snippet shows the fundamental if-else logic separating the base case from the recursive step.

  • Core Snippet 2: Factorial Implementation:

    
    public int factorial(int n) {
    
        if (n == 0) {
    
            return 1;
    
        } else {
    
            return n * factorial(n - 1);
    
        }
    
    }
    

    This is a classic example of recursion where the solution is built by combining n with the solution to the subproblem factorial(n-1).

Core Skill Check

  • Code Tracing: What is the final value returned by mystery(4)?

    
    public int mystery(int n) {
    
        if (n <= 1) { return 1; }
    
        return n + mystery(n - 1);
    
    }
    

    Answer: 10 (which is 4 + 3 + 2 + 1)

  • Debugging: Identify the runtime error in this Java code:

    
    public int sum(int n) {
    
        // Calculates the sum of positive integers up to n.
    
        return n + sum(n - 1);
    
    }
    

    Answer: There is no base case. This will cause infinite recursion and a StackOverflowError.

  • Application: Write a single line of Java code for the recursive step in a method multiply(int a, int b) that calculates a * b using only addition (e.g., 3 * 4 = 3 + 3 + 3 + 3).

    Answer: return a + multiply(a, b - 1);

Common Misconceptions & Errors

  • Forgetting the Base Case: The most common error. Without a base case, the method will never stop calling itself, leading to a StackOverflowError.

  • Recursive Call Does Not Progress Toward the Base Case: The arguments in the recursive call must change in a way that eventually satisfies the base case condition. A call like myMethod(n) calling myMethod(n) will also lead to infinite recursion.

  • Forgetting to return the Recursive Result: In methods that return a value, it's a common mistake to make the recursive call but not use its result. For example, writing factorial(n-1); instead of return n * factorial(n-1);.

  • Unnecessary Complexity: Recursion is elegant for some problems (like tree traversals or factorial) but can be less efficient and harder to read than a simple loop for others (like summing array elements).

Summary

Recursion is a fundamental computer science concept where a method solves a problem by calling itself. A successful recursive implementation requires two parts: a base case that defines a stopping condition, and a recursive step that breaks the problem into a smaller piece and calls the method again. When a recursive method is called, Java uses the call stack to manage each instance's state. While powerful, recursion must be designed carefully; a missing or unreachable base case will cause infinite recursion and a StackOverflowError. For certain problems, recursion provides a solution that is more intuitive and concise than an iterative approach.