Divide &
Conquer
Break the problem into parts, solve each recursively, combine the results. A deceptively simple idea that yields some of the most beautiful algorithms in computer science.
01 The Divide & Conquer Paradigm
"Divide and conquer refers to a class of algorithmic techniques in which one breaks the input into several parts, solves the problem on each part recursively, and then combines the solutions to these subproblems into an overall solution."
02 Counting Inversions
This problem arises directly from collaborative filtering β matching users by taste. The key insight: two rankings are "similar" when few pairs are out of order. How many pairs need to be swapped?
Given an array A[1:n], two indices i < j form an inversion if A[i] > A[j]. The number of inversions measures how far the array is from being sorted. A perfectly sorted array has 0 inversions; the worst case has C(n,2) = n(nβ1)/2 inversions.
Why Not NaΓ―ve O(nΒ²)?
Checking every pair takes O(nΒ²). Connection to insertion sort: each swap in insertion sort eliminates exactly one inversion, so its runtime is O(n + I) where I = inversions. But in the worst case, I = Ξ(nΒ²).
The Trick: Modified Merge Sort
During the merge step, when we pick an element from the right subarray over an element from the left, all remaining left elements form inversions with it. We count these "cross-inversions" for free during the merge.
The key correctness argument: when A[i'] > A[j'] during merge, all elements A[i'], A[i'+1], β¦, A[q] in the left half are also > A[j'] (since the left is sorted). So we count exactly q β i' + 1 new inversions in one step.
Same recurrence as merge sort β because it IS a modified merge sort.
03 Maximum Profit (Investment Problem)
Given stock prices A[1:n] over n days, find buy day i and sell day j β₯ i maximizing profit A[j] β A[i].
Split A[1:n] at midpoint m. The optimal (buy, sell) pair must fall into exactly one of three cases:
Two Versions
Each call scans subarrays for min/max: O(n) combine step β T(n) = 2T(n/2) + O(n) β O(n log n).
Return min and max recursively alongside the best pair β so combine is O(1). Unrolling the recurrence gives linear time.
Upgrade Trick β Returning Extra Info
UpgradedMaximalIncrease(A[l:r]) returns four values: the best (buy, sell) pair, and the indices of the overall min and max in A[l:r]. The crossing case then uses the left's min and the right's max directly β no scan needed. Combining min/max of both halves is O(1).
04 The Master Theorem
A systematic tool for solving recurrences of the form T(n) = aT(n/b) + f(n).
Compare f(n) to the watershed function nlogba:
If f(n) = O(nlogba β Ξ΅) for some Ξ΅ > 0, then T(n) = Ξ(nlogba)
If f(n) = Ξ(nlogba), then T(n) = Ξ(nlogba log n)
If f(n) = Ξ©(nlogba + Ξ΅) for some Ξ΅ > 0, AND af(n/b) β€ cf(n) for some c < 1, then T(n) = Ξ(f(n))
Four Worked Examples from the Notes
| Recurrence | a, b, f(n) | Watershed nlogba | Case | Result |
|---|---|---|---|---|
| T(n) = 9T(n/3) + n | a=9, b=3, f=n | nlogβ9 = nΒ² | Case 1 (Ξ΅=1) | Ξ(nΒ²) |
| T(n) = T(2n/3) + 1 | a=1, b=3/2, f=1 | nlogβ/β1 = 1 | Case 2 | Ξ(log n) |
| T(n) = 3T(n/4) + n log n | a=3, b=4, f=n log n | nlogβ3 β n0.79 | Case 3 (Ξ΅β0.2) | Ξ(n log n) |
| T(n) = 2T(n/2) + n log n | a=2, b=2, f=n log n | nlogβ2 = n | β Master fails! | Ξ(n logΒ²n) |
05 Interactive Master Theorem Calculator
Setting f(n) exponent = k means f(n) = nα΅ (for log n terms use Case 2 directly). Examples preloaded above use Merge Sort defaults (a=4, b=2, f=nΒΉ).
06 Karatsuba's Fast Integer Multiplication
Multiplying two n-bit integers naΓ―vely: O(nΒ²). Can divide-and-conquer help?
The Obvious Split β Still O(nΒ²)
Write x = xβΒ·2n/2 + xβ and y = yβΒ·2n/2 + yβ. Then:
Four n/2-bit multiplications β T(n) = 4T(n/2) + O(n). By Master Theorem: T(n) = O(nlogβ4) = O(nΒ²). No improvement!
Karatsuba's Trick β Three Recursive Calls
Observe that xβyβ + xβyβ = (xβ+xβ)(yβ+yβ) β xβyβ β xβyβ. The three products on the right side reuse xβyβ and xβyβ which we compute anyway!
Pβ = xβyβ β recursive call 1
Pβ = xβyβ β recursive call 2
Pβ = (xβ+xβ)(yβ+yβ) β recursive call 3
xy = PβΒ·2βΏ + (Pβ β Pβ β Pβ)Β·2n/2 + Pβ
07 Strassen's Fast Matrix Multiplication
Standard nΓn matrix multiply needs nΒ³ operations. Partition A, B, C into 2Γ2 blocks of n/2Γn/2 submatrices:
Cββ = AββBββ + AββBββ
Cββ = AββBββ + AββBββ
Cββ = AββBββ + AββBββ
Cββ = AββBββ + AββBββ
T(n) = 8T(n/2) + O(nΒ²) β O(nΒ³) β still cubic!
Pβ = Aββ(BβββBββ)
Pβ = (Aββ+Aββ)Bββ
Pβ = (Aββ+Aββ)Bββ
Pβ = Aββ(BβββBββ)
Pβ
= (Aββ+Aββ)(Bββ+Bββ)
Pβ = (AβββAββ)(Bββ+Bββ)
Pβ = (AβββAββ)(Bββ+Bββ)
Recombining with 7 Products
Cββ = Pβ
+ Pβ β Pβ + Pβ
Cββ = Pβ + Pβ
Cββ = Pβ + Pβ
Cββ = Pβ
+ Pβ β Pβ β Pβ
| Method | Multiplications | Additions | Total Ops |
|---|---|---|---|
| Standard | 8 Γ (n/2)Β² | 4 Γ (n/2)Β² | O(nΒ³) |
| Strassen | 7 Γ (n/2)Β² | 18 Γ (n/2)Β² | O(nΒ²Β·βΈβ°β·) |
08 Fast Polynomial Multiplication (FFT)
Given polynomials A(x) of degree mβ1 and B(x) of degree nβ1, compute C(x) = A(x)Β·B(x) of degree m+nβ2, where cβ = Ξ£α΅’ββ±Όββ aα΅’bβ±Ό.
Naive convolution: O(mn). FFT does it in O(n log n).
Instead of working with coefficients directly, we convert to "point-value" form β evaluate both polynomials at 2n points, multiply the values pointwise, then convert back to coefficients (interpolation).
The FFT Divide & Conquer β Even/Odd Split
Any polynomial A(x) can be split into its even-index and odd-index coefficients:
where Aeven(x) = aβ + aβx + aβxΒ² + β¦ and Aodd(x) = aβ + aβx + aβ xΒ² + β¦
Evaluating at Οβ±ΌΒ² = e2Οij/n (the n-th roots of unity) means we've reduced evaluating one degree-(nβ1) polynomial at 2n points to evaluating two degree-(n/2β1) polynomials at n points.
The Inverse FFT (IFFT)
To recover coefficients from point values, we exploit a beautiful algebraic fact: evaluating the polynomial D(x), whose coefficients are the C-values at roots of unity, at the roots of unity again gives us back 2n times each coefficient cβ. Dividing by 2n recovers C. The IFFT has the same structure as the FFT, so it also runs in O(n log n).
09 Closest Pair of Points
Given n points in the plane, find the pair with smallest distance. NaΓ―ve: O(nΒ²). D&C achieves O(n log n) β the first sub-quadratic algorithm for this fundamental geometry problem, due to Shamos and Hoey (early 1970s).
Why Check Only 7 Points?
This is the geometric key. If two points in the strip Y' are within distance Ξ΄, they both lie in a rectangle of width 2Ξ΄ and height Ξ΄. This rectangle splits on the dividing line β into two Ξ΄ΓΞ΄ halves (one for each side). Within each Ξ΄ΓΞ΄ half, no two same-side points are closer than Ξ΄ (by the recursive guarantee). So each Ξ΄ΓΞ΄ box holds at most one point. There are 4 boxes total on each side β 8 boxes, 8 points max, so at most 7 others to check per point.
Chapter Summary
| Problem | Key Insight | Recurrence | Runtime |
|---|---|---|---|
| Counting Inversions | Count cross-inversions during merge | 2T(n/2) + O(n) | O(n log n) |
| Max Profit (basic) | 3-case split: left / right / cross | 2T(n/2) + O(n) | O(n log n) |
| Max Profit (upgraded) | Return min/max alongside pair | 2T(n/2) + O(1) | O(n) |
| Karatsuba | 3 recursive calls instead of 4 | 3T(n/2) + O(n) | O(nΒΉΒ·β΅βΈβ΅) |
| Strassen | 7 recursive calls instead of 8 | 7T(n/2) + O(nΒ²) | O(nΒ²Β·βΈβ°β·) |
| FFT | Even/odd split at roots of unity | 2T(n/2) + O(n) | O(n log n) |
| Closest Pair | Strip argument: only 7 checks | 2T(n/2) + O(n) | O(n log n) |