Skip to main content

Welcome to a Grasp lesson

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

Lesson 4

Analyzing Recursive Algorithms with Recurrence Relations

Recommended resources

Hello! Welcome back to your daily lesson.

In our last session, we analyzed algorithms in terms of their best, average, and worst-case performance. We identified the complexities of recursive algorithms like Binary Search and Quicksort, but we took those complexities (, ) as given. Today, we bridge that gap.

This lesson directly addresses the learning outcome: Use mathematical recurrence relations to derive the time complexity of recursive algorithms. We will unpack the formal machinery that allows us to move from recursive code to a precise, provable Big O notation. You will learn how to model, visualize, and solve the equations that govern recursive efficiency.


Concept 1: From Recursive Code to Recurrence Relations

The first step in analyzing any recursive algorithm is to translate its structure into a mathematical formula. This formula is called a recurrence relation.

Technical Explanation

A recurrence relation defines a function in terms of itself, just like a recursive algorithm calls itself. It consists of two parts:

  1. Base Case(s): The cost of solving the smallest possible problem (e.g., an array of size 1), which doesn't lead to further recursion. We usually express this as a constant, like or simply .
  2. Recursive Case: An equation that expresses the cost for an input of size , , in terms of the cost of solving smaller subproblems.

Let's model the two key recursive algorithms from our last lesson:

  • Binary Search: In each step, it performs one comparison ( work) and then makes one recursive call on a subproblem of half the size ().

    • Recurrence Relation:
  • Merge Sort: In each step, it makes two recursive calls on subproblems of half the size () and then combines the results by merging the two sorted halves, which takes linear time ( work).

    • Recurrence Relation:

Solving Recurrences

For a formal definition of recurrence relations and why they are central to analyzing recursive algorithms, refer to these introductory notes.

Read the 'Introduction' section. Focus on how a recurrence is defined with base and recursive cases and how it naturally arises from the analysis of recursive algorithms.

Metaphor: A Self-Referencing Recipe

Think of a recurrence relation as a recipe for a fractal-like dish.

  • Recursive Case: "To cook a 'Mega-Meal' for n people, first prepare two 'Half-Meals' (for n/2 people each), and then spend n minutes combining them." This corresponds to .
  • Base Case: "A 'Single-Serving' meal takes 1 minute to prepare." This corresponds to .
    Our goal is to solve this "recipe" to find the total cooking time for the Mega-Meal.

Interview Question

"Consider the following Python function that calculates the nth Fibonacci number. Write down the recurrence relation for its time complexity. Don't solve it yet, just model it."

def fib(n):
    if n <= 1:
        return n
    return fib(n-1) + fib(n-2)

Answer: "The base cases n <= 1 take constant time, so . The recursive step makes two calls, one to fib(n-1) and another to fib(n-2), and then does a constant amount of work (one addition). Therefore, the recurrence relation is ."



Concept 2: The Recursion Tree Method — Visualizing the Cost

The recursion tree method is a powerful way to visualize the work done by a recursive algorithm and make an educated guess about its complexity. It's often the most intuitive first step.

Technical Explanation

In this method, we draw a tree to represent the recursive calls. Each node in the tree represents the cost of a single subproblem, and the total cost of the algorithm is the sum of costs of all nodes.

Let's analyze the Merge Sort recurrence: .

Recursion Tree for Merge Sort
A recursion tree for Merge Sort. Each node shows the cost of the 'merge' step at that level of recursion. The total work is the sum of costs across all levels.

Here’s how to break it down:

  1. Root: The root of the tree represents the initial call. The work done at this top level (the cost of the final merge) is . This call spawns two children for the subproblems.
  2. Level 1: We have two subproblems of size . The work for each is . The total work at this level is .
  3. Level i: At depth i, we have subproblems, each of size . The work for each is . The total work at this level is .
  4. Tree Depth: The recursion stops when the subproblem size is 1. This happens when , which solves to . So, the tree has levels.
  5. Total Cost: Since each of the levels contributes to the total work, the overall time complexity is .

This method gives us a strong hypothesis for the algorithm's complexity.

Metaphor: A Project Delegation Hierarchy

Imagine a CEO (the root call) needs to complete a project.

  • She spends n hours on high-level strategy (the work at the root).
  • She delegates the project to two VPs (2 children). Each VP works on a project of half the scope (n/2 hours of work) and delegates to two directors.
  • The total work at the VP level is hours.
  • This continues down the hierarchy. If the work at every level of the company hierarchy sums to n hours, and the hierarchy is levels deep, the total project cost is person-hours.
Test your understanding!

Draw a recursion tree for the recurrence . What is the total work at each level i? What is the total work dominated by?

Show answer
  • Work at level i: At depth i, there are nodes, each representing a problem of size . The cost at each node is . The total cost at level i is .
  • Total work: The total work is the sum over all levels: . This is a geometric series with a ratio less than 1. Such a series is dominated by its first term.
  • Conclusion: The total work is dominated by the root's work, . So, we can guess the complexity is .


Concept 3: The Substitution Method — Proving the Guess

The recursion tree gives us a good guess, but it's not a formal proof. The substitution method uses mathematical induction to rigorously prove that our guess is correct.

Technical Explanation

The process has two main steps:

  1. Guess the solution: We use the recursion tree or intuition to guess a bound (e.g., ).
  2. Prove by induction:
    • Inductive Hypothesis: Assume the guess is true for all integers smaller than .
    • Inductive Step: Use the recurrence relation and the hypothesis to prove that the guess is also true for .

Let's prove that is .

  1. Guess: From our recursion tree, we guess . Formally, we want to prove for some constant and for all .
  2. Inductive Hypothesis: Assume for all . This implies it holds for , so .
  3. Inductive Step: Substitute this into the recurrence: We need to show this is . This holds if , which simplifies to , or . This is true for any . We have successfully proved our guess.

Substitution method | Solving Recurrences | Data Structure & Algorithm | Appliedroots

This video provides an excellent step-by-step guide to the substitution method. Crucially, it also demonstrates what happens when you make an incorrect guess, which is a common pitfall.

Watch from 00:52 to 15:08. The first part (until 09:42) walks through the correct proof for the Merge Sort recurrence, just like we did above. The second part shows why guessing O(n) fails the induction, which is a critical lesson in why the proof must be exact.

Interview Question

"Suppose you're analyzing a recurrence and use the substitution method. You guess the bound is and your inductive step results in , where is a positive constant. Have you proven your guess? If not, what does this result suggest?"

Answer: "No, the guess has not been proven. The substitution method requires proving the exact form of the inductive hypothesis. Deriving fails to prove . This result suggests that the guess is too low. The extra term, which might seem small, will accumulate at each level of recursion, indicating that the true complexity is likely a higher order than ."



Concept 4: The Master Theorem — The Ultimate Shortcut

For a large class of divide-and-conquer algorithms, we can bypass the recursion tree and substitution methods and get an answer directly using a powerful formula known as the Master Theorem.

Technical Explanation

The Master Theorem applies to recurrences of the form:

where:

  • is the number of subproblems.
  • is the factor by which the input size is reduced.
  • is the cost of the work done outside the recursive calls (dividing the problem and combining the results).

The theorem compares the function to . This critical value represents the rate of growth of the work done at the leaves of the recursion tree. The intuition is to see which part of the algorithm dominates: the work at the root () or the work at the leaves ().

There are three cases:

  1. Case 1: Root-dominated. If for some constant . (i.e., grows polynomially slower than ).

    • Solution:
  2. Case 2: Balanced. If . (i.e., grows at the same rate as ).

    • Solution:
  3. Case 3: Leaf-dominated. If for some constant , AND if for some constant and sufficiently large (this is a "regularity condition").

    • Solution:

Applying the Master Theorem:

  • Merge Sort:

    • .
    • Critical value: .
    • , which matches the critical value. This is Case 2.
    • Solution: .
  • Binary Search:

    • .
    • Critical value: .
    • , which matches. This is Case 2.
    • Solution: .
  • Example from Concept 2:

    • .
    • Critical value: .
    • grows polynomially faster than . This is Case 3. We check the regularity condition: . This holds for .
    • Solution: .

2.4.1 Masters Theorem in Algorithms for Dividing Function #1

For a comprehensive walkthrough of the Master Theorem with numerous examples for each case, watch this video. It clearly explains how to identify 'a', 'b', and 'f(n)' and how to compare the functions to determine the correct case.

Watch the entire video. It systematically covers the general form of the recurrence (0:00-1:18) and then provides detailed explanations and examples for Case 1 (4:32), Case 2 (9:47), and Case 3 (14:42).



Concept 5: Advanced Recurrences & Method Choice

Not all recurrences fit the Master Theorem's tidy format. For these, we must rely on more fundamental methods or transformations.

Technical Explanation

Consider the recurrence for an algorithm that works on a data structure like a B-tree or performs a search on a range by taking its square root:

This recurrence is not in the form , so the Master Theorem does not apply. Here we can use a change of variables (a domain transformation) to convert it into a familiar form.

  1. Define a new variable: Let . This implies .
  2. Substitute into the recurrence:
    • The term becomes .
    • The term becomes .
    • The term becomes .
      The recurrence is now: .
  3. Define a new function: Let . Our recurrence transforms to:

    This is the exact recurrence for Merge Sort! We already know its solution is .
  4. Convert back: Now we substitute back our original variables. Since and :

    This technique demonstrates the power of transforming a problem into one you've already solved.

Choosing Your Method:

  • Recursion Tree: Always a great starting point for building intuition and generating a guess. It's visual and hard to get wrong conceptually.
  • Master Theorem: Your first choice for any divide-and-conquer recurrence that fits the pattern. It's the fastest method.
  • Substitution Method: The fundamental proof technique. Use it when the Master Theorem doesn't apply, or when an interviewer explicitly asks you to "prove from first principles."
  • Transformations: A powerful tool for recurrences with unusual arguments (like or ). The goal is to transform them into a form solvable by the other methods.


Conclusion

Today, you've acquired the essential mathematical toolkit for analyzing recursive algorithms. You can now formally justify the performance claims we've made in previous lessons.

Key Takeaways:

  • Recurrence Relations are the mathematical models of recursive algorithms.
  • The Recursion Tree Method provides a visual way to sum up the work done at all levels of recursion and generate a complexity guess.
  • The Substitution Method uses mathematical induction to formally prove a complexity bound, making it the most rigorous technique.
  • The Master Theorem is a powerful shortcut for solving a common class of divide-and-conquer recurrences by comparing the work at the root versus the leaves.
  • For non-standard recurrences, techniques like change of variables can transform them into a solvable form.

Preview of the Next Lesson

We've now completed our initial deep dive into complexity analysis. Our next lesson will transition from theory to practice by starting our exploration of core sorting algorithms. We'll begin with the simpler, algorithms: Bubble Sort, Insertion Sort, and Selection Sort. While not optimal, analyzing their mechanisms provides a crucial foundation for understanding the more advanced algorithms to come.