Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 25

Understanding Recursion: Base Cases and Recursive Steps

Recommended resources

Hello! Welcome to the first lesson in our new module on Recursion.

In the previous module, we focused on analyzing the efficiency of algorithms that use loops for repetition. We learned how to use Big O notation to describe their performance in the best, worst, and average cases. Today, we're going to explore a completely different and very powerful way to solve problems that involve repetition: recursion.

Recursion is a fundamental concept in computer science where a function solves a problem by calling itself. It's a common topic in technical interviews, and mastering it will allow you to think about problems in a new light.

Your learning outcome for this lesson is to explain recursion by identifying the base case and the recursive step in a function. These are the two essential components that make recursion work.

A New Way of Thinking About Problems

At its core, recursion is about breaking a large, complex problem into smaller, identical sub-problems until you reach a problem so simple that it can be solved instantly.

To build an intuition for this, let's watch a short video that uses a couple of great analogies to explain this way of thinking.

Recursion in Programming - Full Course

This video from freeCodeCamp.org uses analogies like waiting in an ATM line and revising an essay to introduce the core ideas of recursion. It's a great, non-technical starting point.

Watch from the beginning (00:41) to 04:50. As you watch, focus on the two key questions that are asked for solving a problem recursively: 'What's my stopping condition?' 'How do I break this problem down into some sub-problem?' (or 'What's the least amount of work I can do?')

The video introduces the two fundamental pillars of any recursive solution. In programming, we have specific names for them:

  1. The "stopping condition" is called the base case.
  2. The "breaking it down into a sub-problem" part is called the recursive step or recursive case.

Every recursive algorithm you encounter will have these two parts. Let's formalize these definitions.


The Two Pillars of Recursion

For a recursive function to work correctly, it absolutely must have a base case to prevent it from calling itself forever.

Iterative vs. Recursive Approach to Searching
A visual comparison of an iterative (loop-based) and a recursive approach. The recursive approach repeatedly applies the same logic ('look for key') to a smaller part of the problem (an inner box) until it hits the base case (finds the key).

This next reading provides a clear definition of the base case and recursive case, and shows what happens when a base case is missing.

How Recursion Works

This article from freeCodeCamp explains the concepts with simple flowcharts and a straightforward 'countdown' code example.

Read the section titled 'Base case and recursive case'. Pay close attention to the countdown function example and how adding a base case prevents an infinite loop.

To summarize and solidify those key points:

  • Base Case: This is the simplest possible version of the problem, one that the function can solve directly without calling itself again. It acts as the exit condition for the recursion. It's often found inside an if statement.
  • Recursive Step: This is where the magic happens. The function calls itself, but with an input that is somehow "smaller" or "closer" to the base case. This ensures that the function makes progress toward the stopping condition with each call.

A recursive function without a base case is like a while True: loop with no break statement—it will run forever (or until your computer runs out of memory and crashes).


A Classic Example: The Factorial Function

Let's apply these concepts to a classic mathematical function that lends itself well to recursion: the factorial. Your math background will be helpful here.

The factorial of a non-negative integer n, written as n!, is the product of all positive integers less than or equal to n.
For example, 4! = 4 * 3 * 2 * 1 = 24.

Notice a pattern here: 4! = 4 * (3 * 2 * 1) = 4 * 3!.
We can generalize this. For any integer n > 0:

This looks exactly like a recursive step! We are defining the factorial of n in terms of the factorial of a smaller number, n-1.

But what's the base case? We need a value that is defined directly. By mathematical convention, 0! = 1. This is our stopping point.

This video does an excellent job of walking through this exact thought process.

Introduction to Recursion (Data Structures & Algorithms #6)

In this video, CS Dojo explains how to derive the recursive definition of a factorial and why the base case is essential for it to work.

Watch from the beginning to 04:08. Follow the logic as the presenter reframes the standard definition of a factorial into a recursive one and discovers the need for a base case when n=0.

Now, let's see how this translates directly into Python code.

def factorial(n):



    # Base Case: The simplest case that we can solve directly.
    if n == 0:
        return 1



    # Recursive Step: We solve a smaller version of the same problem.
    else:
        return n * factorial(n - 1)




# Example call
print(factorial(4)) # Output will be 24

In the code above:

  • The if n == 0: block is the base case. It stops the recursion.
  • The line return n * factorial(n - 1) is the recursive step. It calls the same function with a smaller input (n-1).

Your Turn: Identify the Parts

Let's look at another simple problem: calculating the sum of all integers from 1 to n.
For example, sum(4) = 4 + 3 + 2 + 1 = 10.

We can define this recursively: sum(n) = n + sum(n-1).
The base case would be sum(1) = 1.

Here is the Python code for this function. Can you identify the base case and the recursive step?

def sum_recursive(n):
    if n == 1:
        return 1
    else:
        return n + sum_recursive(n - 1)

Take a moment to decide which part is which.

...

The if n == 1: return 1 line is the base case. If the input n is 1, the function just returns 1 without making another call.

The else: return n + sum_recursive(n - 1) block contains the recursive step. It calls sum_recursive again, but with n-1, moving closer to the base case.

This image provides a great visual breakdown of this exact function.

Understanding Recursion: Sum of Numbers from 1 to n
This diagram shows the `sum_recursive` function in action. It clearly labels the base case and the recursive step in the code, and then traces how `sum_recursive(4)` is broken down into smaller calls until it hits the base case.

Conclusion

Excellent work today! You've just been introduced to a powerful new programming paradigm. It can feel a bit strange at first, like a snake eating its own tail, but it's an elegant way to solve many complex problems.

Key Takeaways:

  • Recursion is a problem-solving technique where a function calls itself to solve smaller instances of the same problem.
  • A recursive function is composed of two critical parts:
    • A base case: A simple condition where the function stops calling itself and returns a value directly.
    • A recursive step: Where the function calls itself with an input that progresses towards the base case.
  • A recursive function that lacks a base case, or can never reach it, will result in an infinite loop.

Preview of the Next Lesson:
Now that you can identify the components of a recursive function, the next step is to understand how the computer keeps track of all these nested calls. In the next lesson, we will implement a simple recursive function (factorial) and trace its execution using the concept of the call stack. This will demystify how the intermediate results are stored and combined to produce the final answer.