Divide and Conquer Patterns

Divide and Conquer প্যাটার্ন

Read: ~40 min Advanced 6 practice problems Live code runner

1. The D&C Template

Divide the input into smaller subproblems, conquer each recursively, and combine. The recurrence T(n) = a · T(n/b) + f(n) determines complexity via Master Theorem (Module 05). Beyond merge/quick sort, D&C powers many of the fastest algorithms we know.

Divide → Conquer → Combine — সব D&C-এর কঙ্কাল। complexity-এর হিসেব Master Theorem দিয়ে দ্রুত পাওয়া যায়।

2. Closest Pair of Points — O(n log n)

Given n points in the plane, find the two with smallest Euclidean distance. Brute force is O(n²). The D&C version: sort by x, recurse on left and right halves to get min distances δ_L and δ_R, take δ = min. Then check the "strip" of points within δ of the dividing x-line — sorted by y, each point only needs to compare with the next 7 in the strip (a pigeon-hole geometric argument). Total O(n log n).

Why "next 7 in the strip" suffices In a δ × 2δ rectangle, you can fit at most 8 points such that every pair is at least δ apart (by tiling argument). So when scanning sorted by y, pairs more than 7 apart can't be closer than δ. ∎

3. Karatsuba Multiplication — O(n^log₂3) ≈ O(n^1.585)

Multiply two n-digit numbers. Naive: O(n²). Split each into high and low halves: x = x_H·B + x_L, y = y_H·B + y_L. The naive expansion needs 4 sub-multiplications. Karatsuba's trick: compute three products P₁ = x_H · y_H, P₂ = x_L · y_L, P₃ = (x_H + x_L)(y_H + y_L), then x · y = P₁ · B² + (P₃ − P₁ − P₂) · B + P₂. Three sub-multiplications instead of four. T(n) = 3T(n/2) + n → O(n^log₂3) ≈ O(n^1.585).

চারটি sub-multiplication তিনটিতে নামিয়ে আনা — এটাই Karatsuba-এর মূল কৌশল। বড় integer multiplication-এর ভিত্তি (Python int, GMP, RSA — সব এই idea-এর উপর)।
karatsuba.cpp
#include <bits/stdc++.h>
using namespace std;

long long karatsuba(long long x, long long y) {
    if (x < 10 || y < 10) return x * y;
    int n = max(to_string(x).size(), to_string(y).size());
    int m = n / 2;
    long long B = pow(10, m);
    long long xH = x / B, xL = x % B;
    long long yH = y / B, yL = y % B;
    long long P1 = karatsuba(xH, yH);
    long long P2 = karatsuba(xL, yL);
    long long P3 = karatsuba(xH + xL, yH + yL);
    return P1 * B * B + (P3 - P1 - P2) * B + P2;
}

int main() {
    cout << karatsuba(12345, 6789) << "\n";
    cout << karatsuba(99999999, 99999999);
}

4. Strassen's Matrix Multiplication — O(n^log₂7) ≈ O(n^2.807)

Classical n × n matrix multiply: O(n³). Strassen splits each into 2 × 2 blocks and uses 7 sub-multiplications instead of 8 via clever combinations. Recurrence T(n) = 7T(n/2) + n² → O(n^2.807). The constant factor is large; in practice Strassen wins only beyond n ≈ 1000 and is rarely used in libraries (BLAS uses tuned naive O(n³)).

5. FFT — Polynomial Multiplication in O(n log n)

The Fast Fourier Transform evaluates a polynomial of degree n at n roots of unity in O(n log n) using D&C. Multiplying two polynomials becomes pointwise multiplication in the value domain. This is how big-int libraries push to O(n log n log log n), how convolution-based DP problems get faster, and the backbone of every signal-processing pipeline.

FFT is heavy for ICPC Most contest problems expect 50–80 lines of FFT or NTT (Number Theoretic Transform). Master a clean template; we'll dig deeper in advanced material.

6. Practice Problems

  1. Count inversions in an array using a modified merge sort in O(n log n).
    Inversions গুনুন — modified merge sort।
    ✨ Show Answer (উত্তর দেখুন)

    Approach: during merge, when picking from the right half ahead of the left, count mid − leftIdx as the number of inversions added.

  2. Majority element via D&C (Boyer-Moore is faster, but practice the recursion).
    Majority element — D&C।
    ✨ Show Answer (উত্তর দেখুন)

    Approach: recurse on left and right halves; if both halves have the same majority, return it; otherwise count occurrences of each candidate in the full range — whichever exceeds half is the majority.

  3. Maximum subarray sum via D&C (Kadane is O(n), but D&C is O(n log n)).
    Max subarray sum — D&C version।
    ✨ Show Answer (উত্তর দেখুন)

    Approach: answer is max of (left half answer), (right half answer), (max suffix of left + max prefix of right). T(n) = 2T(n/2) + n → O(n log n). Kadane O(n) is better in practice but the D&C version is a great recursion-tree exercise.

  4. Skyline problem — given building rectangles, find the outline.
    Skyline — D&C-এর সাহায্যে।
    ✨ Show Answer (উত্তর দেখুন)

    Approach: recurse on halves to get two skylines; merge by walking left-to-right with the running max of both heights, emitting changes. O(n log n).

  5. Closest pair of points on a small input — implement and verify against brute force.
    Closest pair — implementation।
    ✨ Show Answer (উত্তর দেখুন)

    Approach: sort by x. recurse on halves; combine via the strip step. Stress-test on n = 100 against O(n²) brute force to verify correctness.

  6. Why is Karatsuba O(n^1.585) and not O(n³)?
    Karatsuba complexity-এর গণনা।
    ✨ Show Answer (উত্তর দেখুন)

    Answer: T(n) = 3T(n/2) + O(n). Master Theorem: a = 3, b = 2, c = log₂3 ≈ 1.585. f(n) = O(n) = O(n^(c−ε)) for some ε > 0 → Case 1 → T(n) = Θ(n^c) = Θ(n^1.585).

Summary — Module 33

Beyond merge sort, D&C unlocks closest-pair O(n log n), Karatsuba O(n^1.585), Strassen O(n^2.807), and the FFT-powered O(n log n) polynomial multiplication. Every algorithm here is a recurrence — Master Theorem reads off complexity at a glance.

"Naive O(n²) এড়াতে চাইলে D&C বা DP" — এটিই সবচেয়ে কাজে লাগানো heuristic। প্রতিটি D&C-এর core trick হলো সাব-প্রবলেমে কোনো শেয়ারিং খুঁজে বের করা।

Next Module → Dynamic Programming I: Foundations।