Chapter 9. Divide and Conquer
Recurrence-driven algorithms: split, recurse on halves, combine. Parallel composition is what makes them fly.
This page: Classical forms. View LLP forms »
This page collects the classical / parallel-composition implementations of the divide-and-conquer algorithms developed in this chapter. The lattice-linear (LLP) reformulations and chapter setup live on the LLP companion page.
MergeSort (parallel)
MergeSort with the two recursive calls composed via [ ... [] ... ] — they
are independent, so an LL backend can dispatch them in parallel. The
Merge aux runs sequentially after both halves are sorted. The
sequential variant lives in
Chapter 4 (Sorting).
Time complexity: $O(n \log n)$, where $n$ is the size of the array.
QuickSort (parallel)
Lomuto-partition QuickSort. The two recursive calls on the left and right partitions are
composed via [ ... [] ... ]; the partition step runs sequentially. The
sequential variant lives in
Chapter 4 (Sorting).
Time complexity: $O(n^2)$ worst case, $O(n \log n)$ on average, where $n$ is the size of the array.
ClosestPair
Plane-sweep closest-pair via divide and conquer. Points are pre-sorted by $x$-coordinate; the shared "best squared distance" register $G[0]$ flows through the recursion as an explicit parameter so the parallel branches see the same value.
Time complexity: $O(n \log^2 n)$, where $n$ is the number of points. (A further refinement — presorting the strip by $y$-coordinate once, outside the recursion — achieves $O(n \log n)$, but its pseudocode isn't given here.)
CountingInversions
Counts inversions $(i, j)$ with $i < j$ and $A[i] > A[j]$ via the MergeSort framework. The merge step counts cross-half inversions for free; total time $O(n \log n)$.
Time complexity: $O(n \log n)$, where $n$ is the size of the array.
Karatsuba
Karatsuba's $O(n^{\log_2 3})$ integer multiplication. Three half-size multiplications ($x_0 y_0$, $x_1 y_1$, $(x_0 + x_1)(y_0 + y_1)$) instead of four; combine by subtracting two of the products from the third.
Time complexity: $\Theta(n^{\log_2 3}) \approx \Theta(n^{1.585})$ for $n$-digit inputs.
Planar Convex Hull
Sort the points by $x$-coordinate and split at the median into $P_L$ and $P_R$; the two recursive sub-hulls are merged via their upper and lower common tangents, each determinable sequentially in $O(n)$ time.
Time complexity: $O(n \log n)$, where $n$ is the number of points.
Strassen
Strassen's matrix multiplication. Instead of the 8 recursive multiplications a naive block decomposition needs, 7 intermediate products $M_1, \ldots, M_7$ suffice, trading one multiplication for a handful of extra additions and subtractions.
Time complexity: $O(n^{\log_2 7}) \approx O(n^{2.807})$ for $n \times n$ matrices ($n$ a power of 2).
FFT
The recursive Fast Fourier Transform evaluates a coefficient vector at the $N$-th roots of unity by splitting on parity of index and combining via the butterfly identity $\hat{a}_k = A_e(\omega^{2k}) + \omega^k A_o(\omega^{2k})$, $\hat{a}_{k+N/2} = A_e(\omega^{2k}) - \omega^k A_o(\omega^{2k})$. Applying the forward transform to two coefficient vectors, multiplying pointwise, and inverse-transforming back gives $O(n \log n)$ polynomial multiplication.
Time complexity: $O(N \log N)$, where $N$ is the (padded, power-of-2) transform length.
Looking ahead
Divide-and-conquer recurrences underpin Chapter 10 (dynamic programming, where overlapping subproblems force memoisation), Chapter 11 (network flow, where augmenting-path methods recurse on residual graphs), and the parallel-prefix / tree-contraction primitives that appear throughout the book's parallel chapters.