What Problem Does the Master Theorem Solve?
A divide-and-conquer algorithm describes its own cost in terms of itself. Merge sort sorts an array by sorting two half-arrays and merging the results, so its running time obeys T(n) = 2T(n/2) + n. That equation is called a recurrence relation, and it is not an answer — you cannot look at it and say how fast merge sort is.
Solving the recurrence means turning it into a closed form like Θ(n log n). There are three standard ways to do that: expand it into a recursion tree and sum the levels, guess an answer and prove it by induction (the substitution method), or — when the recurrence has the right shape — apply the Master Theorem and simply read the answer off. This page is about the third.
The Master Theorem is a lookup table, not a technique. Its entire value is that somebody already did the recursion tree summation in general, so you can skip straight to the result.
The Standard Form
The theorem applies to recurrences that can be written in exactly this shape:
T(n) = a·T(n/b) + f(n), where a ≥ 1 and b > 1 are constants- a — how many subproblems each call creates.
- Merge sort makes two recursive calls, so a = 2. It must be a constant ≥ 1; it does not have to equal b.
- b — the factor by which the input shrinks.
- Halving the array means b = 2. It must be a constant greater than 1, otherwise the recursion never reaches the base case.
- f(n) — everything the call does outside the recursion.
- The splitting, the merging, the partitioning, the combining. For merge sort this is the O(n) merge.
If your recurrence does not fit this template — different-sized subproblems, a subtractive step, a non-constant a — the Master Theorem does not apply, and no amount of rearranging will change that. The section on limitations below covers what to do instead.
Reading a, b and f(n) Off the Code
In practice you extract the recurrence from the function body. Every recursive call contributes to a and b; everything else contributes to f(n):
function mergeSort(arr) {
if (arr.length <= 1) return arr; // base case: O(1)
const mid = Math.floor(arr.length / 2);
const left = mergeSort(arr.slice(0, mid)); // a = 2 calls
const right = mergeSort(arr.slice(mid)); // b = 2 (half the size)
return merge(left, right); // f(n) = O(n)
}Two calls on half the input, plus a linear merge: T(n) = 2T(n/2) + n.
function binarySearch(arr, target, low, high) {
if (low > high) return -1; // base case: O(1)
const mid = Math.floor((low + high) / 2); // f(n) = O(1)
if (arr[mid] === target) return mid;
return arr[mid] < target // a = 1 call
? binarySearch(arr, target, mid + 1, high) // b = 2 (half the range)
: binarySearch(arr, target, low, mid - 1);
}One call on half the input, constant work outside: T(n) = T(n/2) + 1.
Where the Three Cases Come From
Picture the recursion as a tree. The root is the original problem, each node has a children, and sizes shrink by a factor of b as you descend:
| Level | Subproblems | Size of each | Cost of the level |
|---|---|---|---|
| 0 | 1 | n | f(n) |
| 1 | a | n/b | a · f(n/b) |
| 2 | a² | n/b² | a² · f(n/b²) |
| i | aⁱ | n/bⁱ | aⁱ · f(n/bⁱ) |
| log_b n (leaves) | a^(log_b n) = n^(log_b a) | 1 | Θ(n^(log_b a)) |
The recursion stops when the size reaches 1, which takes log_b n levels, and the bottom level holds n^(log_b a) leaves. So the total cost is a contest between two quantities: the work at the leaves, which is Θ(n^(log_b a)), and the work at the root, which is f(n).
That contest has exactly three outcomes, and those outcomes are the three cases. Either the leaves win, or the root wins, or neither does and every level contributes equally.
The Three Cases
| Case | Condition on f(n) | What it means | Result |
|---|---|---|---|
| Case 1 | f(n) = O(n^(log_b a − ε)) | The leaves dominate | T(n) = Θ(n^(log_b a)) |
| Case 2 | f(n) = Θ(n^(log_b a)) | Every level costs the same | T(n) = Θ(n^(log_b a) · log n) |
| Case 3 | f(n) = Ω(n^(log_b a + ε)) and regularity holds | The root dominates | T(n) = Θ(f(n)) |
The function n^(log_b a) that f is compared against is sometimes called the watershed function. Computing it is always the first step, because all three conditions are stated relative to it.
The ε in Cases 1 and 3 matters more than it looks. It requires f to be polynomiallysmaller or larger — smaller or larger by a factor of n^ε for some ε > 0. Being smaller by a factor of log n does not qualify, and that is precisely the gap where the theorem gives no answer at all.
Case 2 also has a commonly used extended form: if f(n) = Θ(n^(log_b a) · log^k n) for some k ≥ 0, then T(n) = Θ(n^(log_b a) · log^(k+1) n). This is what handles T(n) = 2T(n/2) + n log n, giving Θ(n log² n).
Worked Example — Case 2 (Merge Sort)
Solve T(n) = 2T(n/2) + n.
- Identify the parts.
- a = 2, b = 2, f(n) = n.
- Compute the watershed function.
- n^(log_b a) = n^(log₂2) = n¹ = n.
- Compare.
- f(n) = n and the watershed is n. They are the same, so Case 2 applies.
- Apply Case 2.
- T(n) = Θ(n^(log_b a) · log n) = Θ(n log n).
This matches the recursion tree above: every level costs n, and there are log₂n levels.
Worked Example — Case 1 (Leaves Dominate)
Solve T(n) = 4T(n/2) + n.
- Identify the parts.
- a = 4, b = 2, f(n) = n.
- Compute the watershed function.
- n^(log₂4) = n² — four subproblems of half the size produce n² leaves.
- Compare.
- f(n) = n is polynomially smaller than n²: n = O(n^(2−ε)) with ε = 1. Case 1 applies.
- Apply Case 1.
- T(n) = Θ(n^(log_b a)) = Θ(n²).
The linear work at the root is irrelevant here — the tree branches so fast that almost all the cost sits in the leaves.
Worked Example — Case 3 (Root Dominates)
Solve T(n) = 2T(n/2) + n².
- Identify the parts.
- a = 2, b = 2, f(n) = n².
- Compute the watershed function.
- n^(log₂2) = n.
- Compare.
- f(n) = n² is polynomially larger than n: n² = Ω(n^(1+ε)) with ε = 1. Case 3 is a candidate.
- Check the regularity condition.
- a·f(n/b) = 2·(n/2)² = n²/2 ≤ c·n² holds with c = 1/2 < 1, so the condition is satisfied.
- Apply Case 3.
- T(n) = Θ(f(n)) = Θ(n²).
Here the quadratic work at the top level swamps everything below it, so the recursion contributes nothing asymptotically.
A Reference Table of Common Recurrences
| Recurrence | a | b | n^(log_b a) | Case | Solution | Algorithm |
|---|---|---|---|---|---|---|
| T(n) = 2T(n/2) + n | 2 | 2 | n¹ | Case 2 | Θ(n log n) | Merge sort |
| T(n) = T(n/2) + 1 | 1 | 2 | n⁰ = 1 | Case 2 | Θ(log n) | Binary search |
| T(n) = 4T(n/2) + n | 4 | 2 | n² | Case 1 | Θ(n²) | — |
| T(n) = 9T(n/3) + n | 9 | 3 | n² | Case 1 | Θ(n²) | — |
| T(n) = 7T(n/2) + n² | 7 | 2 | n^2.807 | Case 1 | Θ(n^log₂7) | Strassen |
| T(n) = 2T(n/2) + n² | 2 | 2 | n¹ | Case 3 | Θ(n²) | — |
| T(n) = 3T(n/4) + n log n | 3 | 4 | n^0.793 | Case 3 | Θ(n log n) | — |
| T(n) = 8T(n/2) + n³ | 8 | 2 | n³ | Case 2 | Θ(n³ log n) | — |
Strassen's matrix multiplication is the most interesting row. It replaces eight recursive multiplications with seven, dropping a from 8 to 7 — and since the answer is Θ(n^(log₂a)), that single change takes the running time from Θ(n³) to roughly Θ(n^2.807). It is a direct, practical demonstration that a is the parameter worth fighting over.
A Recipe You Can Follow Every Time
- Put the recurrence in standard form and read off a, b and f(n).
- T(n) = aT(n/b) + f(n), with a ≥ 1 and b > 1 both constant.
- Compute the watershed function n^(log_b a).
- This is the total cost of the leaves. Use log_b a = log a / log b if the exponent is not obvious.
- Compare f(n) with n^(log_b a).
- Polynomially smaller → Case 1. The same → Case 2. Polynomially larger → Case 3.
- For Case 3 only, verify the regularity condition.
- a · f(n/b) ≤ c · f(n) for some constant c < 1 and all large n.
- Write the answer that the matching case gives you.
- Case 1 → Θ(n^(log_b a)); Case 2 → Θ(n^(log_b a) log n); Case 3 → Θ(f(n)).
When the Master Theorem Does Not Apply
The theorem is narrow by design, and recognising when it does not fit is as important as applying it when it does:
| Recurrence | Why it fails | What to do instead |
|---|---|---|
| T(n) = 2T(n/2) + n/log n | f is smaller than n but not polynomially smaller | Falls in the gap below Case 2. (The true answer, Θ(n log log n), needs a recursion tree.) |
| T(n) = 2ⁿT(n/2) + n | a is not a constant | The theorem assumes a fixed number of subproblems. |
| T(n) = 0.5T(n/2) + n | a < 1 | You cannot have half a subproblem. |
| T(n) = T(n − 1) + n | The input shrinks by subtraction, not division | This is a decrease-and-conquer recurrence; use the substitution method instead. |
| T(n) = T(n/3) + T(2n/3) + n | The subproblems have different sizes | The theorem needs every subproblem to be the same size. Use a recursion tree. |
| T(n) = T(n/2) + n(2 − cos n) | The regularity condition fails | f grows fast enough for Case 3, but it oscillates, so a·f(n/b) ≤ c·f(n) does not hold. |
The first row is the classic gap case. Here f(n) = n/log n is smaller than the watershed n, but only by a logarithmic factor, not a polynomial one — so Case 1 does not apply, and it is not equal to n either, so Case 2 does not apply. The theorem is simply silent, and you need a recursion tree to find the real answer.
Common Mistakes
- Forgetting that the difference must be polynomial.
- Case 1 needs f to be smaller by a factor of n^ε for some ε > 0. Being smaller by a factor of log n is not enough, and that recurrence falls into the gap where the theorem says nothing.
- Skipping the regularity condition in Case 3.
- It holds for every polynomial f, which is why it is easy to forget — but it is part of the case, and there are standard exercises built on functions where it fails.
- Applying it to subtract-and-conquer recurrences.
- T(n) = T(n − 1) + n is not of the form aT(n/b) + f(n). The Master Theorem cannot touch it.
- Mixing up a and b.
- a is how many calls you make; b is how much smaller each one is. In T(n) = 4T(n/2) + n they are different numbers, and swapping them changes the answer from Θ(n²) to Θ(n log n).
- Worrying about floors and ceilings.
- T(⌊n/2⌋) and T(⌈n/2⌉) give the same asymptotic answer as T(n/2). You can safely ignore them.
- Assuming the theorem covers every divide-and-conquer algorithm.
- Quick sort's worst case is T(n) = T(n − 1) + n, and its average case involves unequal splits. Neither is a Master Theorem problem.
Frequently Asked Questions
What is the Master Theorem used for?
It gives the asymptotic running time of a divide-and-conquer algorithm directly from its recurrence, without expanding a recursion tree or guessing and proving a bound. If a recurrence has the form T(n) = aT(n/b) + f(n) with constant a ≥ 1 and b > 1, you compare f(n) against n^(log_b a) and read the answer off one of three cases.
What do a, b and f(n) mean?
a is the number of subproblems each call creates, b is the factor by which the input size shrinks in each subproblem, and f(n) is the work done outside the recursive calls — the dividing and combining. For merge sort, a = 2, b = 2 and f(n) = n, because it makes two half-size calls and merges in linear time.
Why does merge sort come out as Θ(n log n)?
For merge sort, n^(log_b a) = n^(log₂2) = n, and f(n) = n as well. Since they match, Case 2 applies and the answer is Θ(n log n). Intuitively, each level of the recursion tree costs a total of n, and there are log₂n levels.
When does the Master Theorem not apply?
When a or b is not constant, when a < 1 or b ≤ 1, when the subproblems have different sizes, when the input shrinks by subtraction rather than division, when f(n) differs from n^(log_b a) by less than a polynomial factor, or when the Case 3 regularity condition fails. In all of those situations use a recursion tree or the substitution method.
What is the regularity condition and why does it exist?
It requires that a·f(n/b) ≤ c·f(n) for some constant c < 1 and all sufficiently large n. It says the work at each level really does shrink geometrically as you go down the tree, which is what lets the root's cost dominate the total. It holds automatically for polynomial f, so it usually needs no more than a line to check.
What is the difference between the Master Theorem and the recursion tree method?
The Master Theorem is a shortcut — three cases, no work, but it only fits recurrences of one exact shape. The recursion tree method is a general technique that works on any recurrence, including unequal splits and subtractive ones, at the cost of doing the summation yourself. The Master Theorem is really just the recursion tree argument, solved once in general.
Key Takeaways
- The Master Theorem solves T(n) = aT(n/b) + f(n) for constant a ≥ 1 and b > 1.
- Everything hinges on comparing f(n) with the watershed function n^(log_b a).
- Case 1: leaves dominate → Θ(n^(log_b a)). Case 2: levels tie → Θ(n^(log_b a) log n). Case 3: root dominates → Θ(f(n)).
- The difference in Cases 1 and 3 must be polynomial; a log factor is not enough, and that gap is where the theorem stays silent.
- Case 3 is not finished until you have checked the regularity condition a·f(n/b) ≤ c·f(n).
- Unequal splits, subtractive recurrences and non-constant a all fall outside the theorem — reach for a recursion tree instead.