Chapter 5: Recursion and Divide-and-Conquer Fundamentals
5.05Beginner5 topics20 min1 interactive animation

Recurrence analysis

To predict how fast a recursive algorithm is, write its cost as a recurrence and solve it. The master theorem solves the most common shape, T(n) = a·T(n/b) + n^d, in one step.

Learning goals

  • Turn a recursive method into a recurrence relation
  • Count the nodes of a recursion tree and the depth of the stack
  • Apply the three cases of the master theorem
  • Relate time, recursion stack space and memoization

Prerequisites

Divide and conquerLogarithmsBig-O notation
5.05.1

Recurrence setup

A recurrence expresses the cost of an input of size n in terms of smaller inputs. Read it off the code: the number of recursive calls gives a, how much the size shrinks gives b (or the subtraction), and the work outside the calls gives f(n).

Examples: binary search T(n) = T(n/2) + O(1). Merge sort T(n) = 2T(n/2) + O(n). Factorial T(n) = T(n - 1) + O(1). Naive Fibonacci T(n) = T(n - 1) + T(n - 2) + O(1). Tower of Hanoi T(n) = 2T(n - 1) + O(1).

AlgorithmRecurrenceSolution
Binary searchT(n) = T(n/2) + 1Θ(log n)
Merge sortT(n) = 2T(n/2) + nΘ(n log n)
FactorialT(n) = T(n-1) + 1Θ(n)
Naive FibonacciT(n) = T(n-1) + T(n-2) + 1Θ(φⁿ)
HanoiT(n) = 2T(n-1) + 1Θ(2ⁿ)
5.05.2

Recursive tree size

The number of calls is the number of nodes in the recursion tree. With branching factor a and depth h the tree has up to a^h leaves. For the linear recursion factorial it is n + 1 nodes; for naive fib(n) about 1.6^n; for Hanoi 2^n - 1.

Counting nodes is often the fastest way to find the time when the work per call is constant. Run the Fibonacci animation with n = 5, 6, 7, 8 and compare the node counts to φⁿ.

5.05.3

Call stack depth

The stack depth is the longest chain of pending calls, which is the height of the recursion tree, not its size. Naive Fibonacci makes an exponential number of calls but is only n deep, so it uses O(n) stack. Merge sort is log₂ n deep. Recursive quick sort is n deep in the worst case.

Depth matters for StackOverflowError and for the space complexity of the algorithm (the stack counts as memory).

AlgorithmCallsDepth (stack)
factorial(n)n + 1n + 1
fib(n) naiveabout 1.6^nn
Merge sort2n - 1log₂ n
Binary searchlog₂ nlog₂ n
Quick sort (worst)nn
5.05.4

Master theorem cases

For T(n) = a·T(n/b) + Θ(n^d) with a ≥ 1, b > 1 and d ≥ 0, compare d with the critical exponent log_b a. Case 1: if d < log_b a, then T(n) = Θ(n^(log_b a)); the leaves dominate. Case 2: if d = log_b a, then T(n) = Θ(n^d log n); every level costs the same. Case 3: if d > log_b a, then T(n) = Θ(n^d); the root dominates.

Use the calculator: drag a, b and d, or use the presets. The table shows the work per level of the tree. Whichever case you are in, the shape of that column tells you why: growing, flat or shrinking.

Recurrencelog_b adCaseSolution
T(n) = T(n/2) + 1002Θ(log n)
T(n) = 2T(n/2) + n112Θ(n log n)
T(n) = 3T(n/2) + n (Karatsuba)1.58511Θ(n^1.585)
T(n) = 7T(n/2) + n² (Strassen)2.80721Θ(n^2.807)
T(n) = T(n/2) + n013Θ(n)

Master theorem calculator

Change a, b and d

T(n) = 2·T(n / 2) + n

Try

Critical exponent log_b a

1

Compare with d

d = 1 = 1

Solution · case 2

Θ(n^1 log n)

Case 2: f(n) = n^1 grows at the same rate as n^1, so every level does about the same work and there are log n levels.

Work per level of the recursion tree (n = 2^7 = 128)

LevelSubproblemsSize eachWork eachLevel total
01128128128
126464128
243232128
381616128
41688128
53244128
66422128
712811128

Case 1: level totals grow toward the leaves. Case 2: they stay equal. Case 3: they shrink away from the root. Add them up and the biggest term decides the answer. This table assumes f(n) = n^d with no log factor.

5.05.5

Time-space trade-off

Spending memory can save time. Memoization stores answers to subproblems so each is computed once: naive Fibonacci uses O(n) stack and O(φⁿ) time, the memoized version uses O(n) stack plus an O(n) table and O(n) time.

The reverse also happens: recomputing instead of storing saves memory. Choose by looking at both the recurrence and the stack depth. A bottom-up loop (lesson 5.07) gets the time benefit with O(1) stack.

Fibonacci versionTimeExtra space
Naive recursionO(φⁿ)O(n) stack
Memoized recursionO(n)O(n) table + O(n) stack
Bottom-up with an arrayO(n)O(n)
Bottom-up with two variablesO(n)O(1)

Practice ladder

Now try it yourself

Easy

  • Write the recurrence for binary search and solve it
  • Draw the recursion tree of fib(5) and count its nodes

Medium

  • Solve T(n) = 4T(n/2) + n² with the master theorem
  • Find the recurrence of recursive power (halving) and its solution
  • Explain why T(n) = 2T(n-1) + 1 is 2ⁿ - 1

Advanced

  • Solve T(n) = T(n/3) + T(2n/3) + n with a recursion tree
  • State the master theorem with a log factor
  • Compare the Akra-Bazzi bound for T(n) = T(n/5) + T(7n/10) + n

Key takeaways

  • Read a, b and f(n) from the code to write the recurrence; solve it with a tree or the master theorem.
  • Compare d with log_b a: leaves dominate, all levels equal, or the root dominates.
  • Time is calls, space is depth; memoization trades memory for far fewer calls.