Motivating examples (fingerprinting, Karger min-cut, QuickSort, Freivalds) where a few coin flips replace heavy deterministic work at a tiny, controllable error.
Basic models and complexity classes — what a randomized algorithm is formally, and the classes RP, coRP, BPP, ZPP, PP.
Methods — the recurring tricks (probability amplification, the probabilistic method, fingerprinting, random walks, …).
More about complexity classes — relationships between them.
Derandomization — removing the randomness while keeping the speed.
This first lecture is just a gallery. Each example is a small story whose punchline is the same: a few random coin flips can replace a lot of deterministic work, at the price of a tiny, controllable probability of error. The recurring questions are always:
What is the resource we save (communication bits? comparisons? time?)
What is the probability of error, and can we make it as small as we like?
1. Database equivalence — fingerprinting with primes
The problem
Two computers, RI and RII, each hold an n-bit string:
RI holds X=x1x2…xn∈{0,1}n,
RII holds Y=y1y2…yn∈{0,1}n.
We want to test whether X=Y while sending as few bits across the network as possible. Read the bit strings as integers:
x=bin(X),y=bin(Y),0≤x,y<2n.
The trivial deterministic solution is to ship all n bits of one string to the other side. We want to do dramatically better.
The protocol
RI picks a random primep from the primes up to n2:
p∈RPrimes(n2).
Then:
RI computes the fingerprints=xmodp and sends the pair (p,s) to RII.
RII computes r=ymodp and answers “equal” iff s=r.
Both p and s are numbers below n2, so each needs about log(n2)=2logn bits.
Communication cost:≈4logn bits, versus n bits for the deterministic protocol. An exponential saving.
Correctness
If X=Y, then x=y, so xmodp=ymodpalways — the answer is correct.
If X=Y, the protocol errs only whenx≡y(modp), i.e. when p divides x−y.
So the one-sided error appears only on unequal inputs, and only for the “unlucky” primes that happen to divide the difference.
Probability of error
Suppose X=Y, so x−y=0. The fingerprint fails exactly for primes p dividing x−y:
perr=∣Primes(n2)∣#{p∈Primes(n2):p∣(x−y)}.
How many bad primes are there? Write the prime factorization
∣x−y∣=pi1j1pi2j2⋯pikjk,jt>0.
Each prime is ≥2, and ∣x−y∣<2n, so the number of distinct prime factors satisfies
2k≤∣x−y∣<2n⟹k≤n−1.
So at most n−1 primes can divide x−y.
How many primes are there to choose from? By the prime-counting estimate
∣Primes(m)∣∼lnmm,here m=n2,
so ∣Primes(n2)∣∼lnn2n2=2lnnn2.
Putting it together:
perr≤n2/(2lnn)n−1<n2lnn.
Punchline. With only O(logn) communicated bits we get error O(nlnn), which already vanishes as n grows — and could be driven down further by repetition.
Why primes? The bound k≤n−1 uses only that distinct primes multiply up fast. Choosing the modulus from a pool (∼n2/lnn primes) much larger than the number of bad ones (≤n−1) is exactly what makes a random pick almost surely good. This trick — replacing an object by its fingerprint modulo a random prime — comes back again and again.
2. Two-way probabilistic finite automaton (2PFA) for anbn
Naming.2PFA = two-way probabilistic finite automaton. The “2” means the read head can move both directions, so the machine can re-scan the input as many times as it wants. That two-way ability is exactly what makes this algorithm possible — and it returns as the punchline at the end.
What we are up against
L={anbn∣n∈N} is the classic non-regular language. A deterministic finite automaton has fixed, finite memory, but comparing two arbitrary counts n and m needs unbounded memory — so no DFA can do it.
Our model adds two small powers:
two-way head — it can go back and re-scan the input as often as it likes;
a fair coin — equivalently, an extra tape of random 0/1 bits it may read.
With these we can recognize L, but only with bounded error. Constants k and L control how small that error is.
The one idea: compare 2−n and 2−m instead of n and m
We cannot store n or m, but we can turn a count into a probability:
Sweep over the block of a’s, flipping a coin above each one. The event “all n coins came up heads” has probability exactly 2−n.
Do the same over the b’s and you get an event of probability 2−m. Now the comparison is easy in spirit:
if n=m, the two rare events 2−n and 2−m are equally likely;
if n=m, the larger block has the rarer “all heads” event.
The machine never learns n or m — it only feels which of the two events fires more often.
The algorithm
Input w∈{a,b}∗; constants k,L control the error.
Cheap deterministic sieve. Check that w has the shape anbm (all a’s, then all b’s) and that n≡m(modk). Both need only finite memory (counting mod k is k states). If either fails, reject.
The coin-flip race. Repeatedly sweep the input, flipping a coin over each symbol. Per sweep:
a-success = every one of the na’s flipped 1 (and the b-block came out mixed, both 0 and 1) — probability ≈2−n;
b-success = every one of the mb’s flipped 1 (and the a-block came out mixed) — probability ≈2−m.
(The “other block is mixed” clause only makes a-success and b-success mutually exclusive — at most one per sweep — so the race below is well defined. It barely changes the probabilities.)
The decision. Watch the sequence of successes. Reject if La-successes occur before any b-success, orLb-successes occur before any a-success. Otherwise accept.
In words: if one side runs away with the race, the counts are unequal → reject; if the race stays balanced, the counts are equal → accept.
Why step 1 (the mod-k check) is not optional
It does two jobs:
It instantly rejects wrong-shape strings and everything with n≡m(modk) — all of which are genuinely not in L.
The crucial one: if a string survives step 1 but still has n=m, then n−m is a nonzero multiple of k, so
∣n−m∣≥k.
That guarantees a minimum gap of k between the counts — exactly what makes the two rare events differ by a usable factor. Without it, n and m could differ by just 1, so 2−n and 2−m would differ by only a factor of 2 — too weak to detect reliably.
Correctness — the two cases
Case n=m (string is in L → we want to accept).a-success and b-success are equally likely, so each success in the race is a-type or b-type with probability 21, independently. We wrongly reject only if the first L successes are all the same type:
preject=either side2⋅(21)L=21−L.
With L=3: preject=0.25, i.e. we correctly accept with probability 0.75.
Case n>m (string not in L → we want to reject).
Because step 1 forces n≡m(modk), if n=m then n=m+ik≥m+k. An a-success now needs kextra heads compared to a b-success, so it is at least 2k times rarer:
Pr[a- or b-success]Pr[a-success]≤2k+11.
So b-successes dominate the race, and we correctly reject with probability
preject≥(1−2k+11)L.
With L=3,k=2: (54)3=0.512.
input
should
correct with prob.
anbn
accept
≥0.75
wrong counts
reject
≥0.512
Both are bounded away from 21, so this is genuine bounded error. The gap is modest; amplify it the usual way — run many independent copies and take a majority vote (and tune k,L).
Subtle tension (good oral-exam point). Raising L shrinks the n=m error 21−L — but it also shrinks the reject probability (1−2k+11)L in the n=m case (a base below 1 raised to a higher power). So you cannot just crank L; you must raise k alongside it (a bigger guaranteed gap ⇒ a bigger per-success bias) to keep both errors small.
The catch: correct but exponentially slow — the deep point
An a-success has probability ≈2−n per sweep, so you expect to wait about 2n sweeps just to see one. Hence the machine recognizes {anbn} with bounded error but in expected exponential time.
This is not a flaw of this particular construction — it is unavoidable (Dwork–Stockmeyer, building on Freivalds):
Any bounded-error 2PFA recognizing a non-regular language must run in expected exponential time.
Punchline. A two-way finite automaton plus a coin is just barely powerful enough to escape regularity — and it pays for that power with exponential time. Randomness buys a new capability here, and the price tag is explicit.
Output: a partition of V into V1,V2 minimizing the number of crossing edges ∣E∗∣=∣(V1×V2)∩E∣.
Best deterministic algorithms run in O(n3) (or O(∣V∣∣E∣log(∣V∣2/∣E∣))). The randomized algorithm is strikingly simple.
The algorithm: random edge contraction
1. label(v) ← v for every vertex
2. while more than 2 vertices remain:
pick e = (x, y) ∈_R E uniformly at random
contract e: merge x and y into a single vertex z (G ← contract(G, e))
label(z) ← label(x) ∪ label(y) (keep parallel edges, drop self-loops)
3. now G has exactly two vertices u, v:
return (label(u), label(v))
Each contraction merges the two endpoints of a random edge into one super-vertex, keeping multi-edges (they represent “how strongly connected” the groups are) but deleting loops. When only two super-vertices remain, their labels are the two sides of the cut. Complexity O(n2) per run.
Analysis
Fix a particular minimum cut Cmin of size k (assume for simplicity it is unique). The algorithm returns Cminiff it never contracts one of its k edges.
Key fact — minimum degree. Every vertex has degree ≥k (otherwise the single-vertex cut around it would be smaller than k). Hence
∣E∣=21v∑deg(v)≥2nk.
Let Ei be the event “Cmin has survived the first i contractions”, and let G/Fi be the graph after contracting the edges Fi of the first i steps. The same degree argument on G/Fi (which has n−i super-vertices) gives
∣E(G/Fi)∣≥2(n−i)k.
Step 1 survives: we must avoid the k cut-edges out of ≥nk/2 edges,
One run finds a fixed minimum cut with probability >2/n2. That looks tiny, but it is polynomially small, so a polynomial number of independent runs makes failure exponentially small.
Amplification by repetition. Failure of one run is ≤1−2/n2, so after t independent runs (keeping the best cut found),
Pr[all fail]≤(1−n22)t≤e−2t/n2.
Taking t=2n2logn gives error ≤e−logn=n1=O(1/n).
Total time:O(n2)⋅t=O(n4logn). 🙂 correct with high probability, 🙁 slower than the deterministic algorithm as written.
Punchline. A laughably simple “keep merging random edges” routine has a guaranteed good success probability per run, and repetition turns that into high confidence. (Later improvements — Karger–Stein — cut the time dramatically by recognizing that early contractions are safe and only the late ones are risky.)
4. Randomized QuickSort (RQS)
The algorithm
RQS(A):
if A = {b}: return b
else:
pick pivot b ∈_R A (uniformly random)
S< = { a ∈ A : a < b }
S> = { a ∈ A : a > b }
return ( RQS(S<), b, RQS(S>) )
Assume the elements are distinct. The cost = number of comparisons, which depends entirely on the random pivot choices:
always picking an extreme element: T(n)=∑2≤i≤ni=O(n2);
always picking the median: T(n)≤2T(n/2)+n−1=O(nlogn);
even a lopsided but balanced-ish split works: T(n)≤T(n/8)+T(7n/8)+n−1=O(nlogn).
The point: any split that is “not too extreme” already gives O(nlogn). With a random pivot, balanced-enough splits are the typical case. Let’s prove the expected cost is O(nlogn).
Analysis via indicator variables
Let s1<s2<⋯<sn be the sorted output. For a particular computation C and a pair i<j, define the indicator
Xij(C)={10if si and sj are compared during C,otherwise.
Total comparisons: T(C)=1≤i≤n−1∑j>i∑Xij(C). By linearity of expectation,
E[T]=i<j∑E[Xij]=i<j∑pij,pij:=Pr[si,sj are compared].
(The crucial move: E[Xij]=1⋅pij+0⋅(1−pij)=pij. Linearity lets us add up these probabilities even though the Xij are highly dependent.)
Computing pij — the key combinatorial insight
Consider the set {si,si+1,…,sj} of j−i+1 consecutive elements.
si and sj are compared if and only if one of them is the first pivot chosen from this whole set.
Why: if some middle element r with si<r<sj is picked first, it separates si and sj into different sub-arrays, and they never meet again. They are compared only if si or sj itself is the first pivot among the j−i+1 candidates. Since the first pivot in that set is uniform over all j−i+1 of them, exactly 2 of those choices (si or sj) cause a comparison:
(Here k=j−i+1 ranges over 2,3,…, and Hn=∑k=1n1/k≈lnn is the harmonic number.)
Punchline. Expected ≈2nlnn comparisons. The art is: (1) charge cost to pairs, (2) use linearity of expectation to ignore dependencies, (3) reduce each pair’s probability to a clean “who is picked first” question. This indicator-plus-linearity pattern is one of the most reused tools in the whole course.
5. Freivalds’ test: is AB=C?
The problem
Given three n×n matrices A,B,C, decide whether AB=C. Recomputing AB costs O(n2.37…) (or naively O(n3)). Freivalds (1977)verifies a claimed product in only O(n2).
The algorithm
Pick a random vector x∈R{0,1}n.
Check whether A(Bx)=Cx.
Why O(n2): never form the matrix product. Compute Bx first (a matrix–vector product, O(n2)), then A(Bx) (O(n2)), and Cx (O(n2)). Three cheap matrix–vector multiplies.
Correctness
If AB=C: then ABx=Cx for every x — always correct.
If AB=C: the test wrongly says “equal” only if (AB−C)x=0 for the random x we happened to pick.
Error probability (the {0,1} version)
Let D=AB−C=0, so some entry Dij=0. Look at coordinate i of y=Dx:
yi=k∑Dikxk=Dijxj+k=j∑Dikxk.
Principle of deferred decisions: fix all coordinates xk (k=j) first. Then yi=0 forces exactly one value of xj:
xj=−Dij∑k=jDikxk.
There is at most one such value, and xj is a fair coin over {0,1}, so it equals that value with probability ≤1/2:
Pr[error]≤Pr[yi=0]≤21.
Repeating with independent random x drives the error to 2−t.
Real-valued version (Vandermonde / polynomial view)
Instead of a 0/1 vector, pick a random real r∈RR and set x=(1,r,r2,…,rn−1)T. Then coordinate i becomes a polynomial in r:
yi=pi(r)=k=0∑n−1Dikrk,degpi≤n−1.
If D=0, some pi is a nonzero polynomial of degree ≤n−1, hence has at most n−1 roots. So
Pr[error]≤Pr[r is a root of pi]=∣R∣n−1,
where we draw r from a finite set R⊆R. This is a baby case of the Schwartz–Zippel lemma.
Punchline. Verifying is cheaper than computing. A single random vector “probes” the matrix difference, and a nonzero difference is almost surely exposed. This is the prototypical fingerprinting of a linear-algebra identity.
6. “Derandomizing” AB=C for integer matrices
Can we remove the randomness entirely? For integer-coefficient matrices, yes — by choosing one cleverly large evaluation point instead of a random one.
Cauchy’s root bound (1829)
Theorem (Cauchy). Let P(x)=akxk+⋯+a1x+a0 be a real polynomial. If x is a root of P, then
∣x∣<1+∣ak∣A,A=0≤i≤kmax∣ai∣.
In words: all roots of a polynomial live inside a disk whose radius is controlled by its coefficients. So if we evaluate at a point bigger than this bound, we are guaranteed not to be sitting on a root — unless the polynomial is identically zero.
The derandomized check
The row polynomials pi(r)=∑kDikrk of D=AB−C have integer coefficients we can bound. If every entry of A,B,C is bounded by
cmax=max{∣aij∣,∣bij∣,∣cij∣},
then each entry of D=AB−C is at most ncmax2+cmax in absolute value (sum of n products, each ≤cmax2, plus one subtracted entry ≤cmax). Plugging into Cauchy’s bound, any real root has magnitude <1+ncmax2+cmax. So pick
α=ncmax2+cmax+1,r←α,x=(1,r,…,rn−1)T,
and check ABx=?Cxdeterministically. Because α exceeds every possible root, the only way Dx=0 is D=0.
Complexity:O(n2) algebraic operations.
Punchline. Randomness was only used to “dodge the roots”. Once we can bound where the roots are, a single well-chosen point dodges them for free. This is the spirit of derandomization — the topic of the last block of the course.
7. Nondeterministic matrix multiplication
Now turn the verifier into a way to certify a guessed product — i.e. put matrix multiplication into a nondeterministic setting.
Over Q
Guess the result C.
Compute α as above and x=(1,α,…,αn−1)T.
VerifyABx=Cx deterministically (single point suffices, by §6).
Over R
GuessC.
Take distinct reals r1,…,rn and build xi=(1,ri,…,rin−1)T.
Then AB=C⟺ABxi=Cxi for all i=1,…,n.
Complexity: the vectors xi are Vandermonde, so Bxi and Cxi can be batched by divide-and-conquer in O(n2log2n), or with the FFT in O(n2logn).
Caveat (!!): once you compute A(Bx), the inner result Bx no longer has the nice Vandermonde “good form”, so you cannot recursively exploit the structure on the outer multiply. The trick has to be applied carefully.
The bilinear form trick
Fold both sides into a single quadratic form. Since D=AB−C:
D=0⟺xTDx=0 for enough x⟺(xTA)(Bx)=?xTCx.
Corollary. Let D be a real n×n matrix, let r1,…,r2n−1 be distinct reals, and xi=(1,ri,…,rin−1)T. Then
D=0⟺∀i:xiTDxi=0.
Why 2n−1 points? The scalar xiTDxi=∑a,bDabria+b is a polynomial in ri of degree at most 2n−2. If D=0 this polynomial is nonzero, hence has at most 2n−2 roots — so checking 2n−1 distinct points is enough to be sure.
Theorem. Multiplication of real matrices can be realized on an N-RealRAM (nondeterministic real RAM) using O(n2logn) (resp. O(n2log2n)) algebraic operations.
Punchline. “Guess the answer, then verify it cheaply” — the verifier from §5–6 is exactly the certificate-checker that places the problem in a nondeterministic class.
8. Nondeterministic multiplication over Z and Zp
Why move to modular arithmetic
The evaluation points blow up: rn−1 with r≈2n−1 is a number (2n−1)n−1, i.e. about O(nlogn)bits long. Arithmetic on such giant integers is expensive. Fix: work modulo a prime p in the field Zp, keeping numbers small.
Two subtleties arise:
Cauchy’s bound no longer holds in Zp — there is no notion of “magnitude” to bound roots.
A value that is not a root over Z might become a root over Zp. Example: x2+1 has no integer root, but over Z5 it has roots 2 and 3.
However, a polynomial of degree n still has at most n roots in any field Zp. That is all we need.
Lemma. Let D be an integer n×n matrix with max∣dij∣≤δ. Let Zp be a field with p>max{δ,2n−1}. Let r1,…,r2n−1<p be distinct, and xi=(1,ri,…,rin−1)T. Then
D=0(in Z)⟺∀i:xiTDxi≡0(in Zp).
Choosing p larger than the entries (δ) and larger than the degree (2n−1) prevents both spurious roots and overflow-collapse, so testing over Zp faithfully decides the integer question.
The sign problem when guessing C
When we guess C nondeterministically we must handle signs. Split each matrix into a positive-entry part and a negative-entry part, A=A++A−, B=B++B−:
(A++A−)(B++B−)=C+A+B++A−B−+C−A−B++A+B−.
This costs 4 multiplications instead of 1, but each now has consistent signs.
How to find a suitable prime p
Guess p. Bertrand’s postulate guarantees one nearby: ∀k>1∃ prime p with k<p≤2k.
Verify p is prime by guessing a short Pratt certificate (1975): verification takes O(log2p) modular multiplications on a unit-cost RAM. (Details in §9.)
Complexity of the whole nondeterministic multiplication:
unit-cost RAM: O(n2log2n);
log-cost RAM: O(n2logn⋅M(logp)), where M(logp) is the cost of multiplying logp-bit numbers.
The previous section needed to certify that a number p is prime. Pratt’s theorem says this can always be done with a short, checkable proof.
Theorem (Pratt). Every prime has a short certificate.
The idea
If p is prime, then Zp∗ is cyclic and has a generatorx of order p−1. Being a generator (a primitive root) is exactly the witness of primality, and it can be checked by a few modular exponentiations.
The axiomatic proof system
Triples (p,x,a) mean “so far we have verified that the order of x is a multiple of a”:
Axiom A:(p,x,1) is an axiom.
Rule R1:(p,x,a),q↦(p,x,qa) provided q∣(p−1) and x(p−1)/q≡1(modp).
Rule R2:(p,x,p−1)↦p provided xp−1≡1(modp).
We prove three things:
p is prime ⟺p is a theorem of the system.
The proof of primality of p has O(logp) lines.
Verifying a proof on a unit-cost RAM costs O(log3p⋅loglogp) operations.
(1 ⇒) If p is prime, then p is a theorem
Let x be a generator of Zp∗ and p−1=q1q2⋯qk the factorization into primes. Build the proof by induction:
Bases 2,3 are prime (handled directly).
Let Di be the proof that each factor qi is prime.
Each R1 step confirms x(p−1)/qi=1, certifying that the order of x is divisible by qi; together they force the order to be exactly p−1, so x really is a generator.
(1 ⇐) If p is a theorem, then p is prime
By contradiction. Suppose p is not prime but is a theorem. Then Zp has no generator. The last proof line must be (p,x,p−1)↦p with xp−1≡1(modp). Since x is not a generator, xj≡1(modp) for some j<p−1 with j∣(p−1). But to reach (p,x,p−1) from (p,x,1) the proof had to apply R1, which requires x(p−1)/qi=1 at each step — contradicting that the true order j is a proper divisor of p−1. Hence p must be prime.
(2) The proof has at most ⌈4logp⌉ lines
By induction.
Basep=2,3: 5 lines suffice.
Hypothesis: the proof of any prime q has ≤⌊4logq⌋−4 lines.
The construction in (1) for p with p−1=q1⋯qk uses: A + R2 + (proofs of all qi) + k×R1. Counting lines:
(using logq1+⋯+logqk=log(q1⋯qk)=log(p−1)<logp). Adding the 5 base lines for the 2,3 cases:
length<⌊4logp⌋−4+5≤⌈4logp⌉.
So the certificate is logarithmic in the size of p — genuinely short.
(3) Verifying the proof is cheap
The only nontrivial operation is computing xbmodp, done deterministically by repeated squaring:
init: (x,b,1);
b even: xb=(x2)b/2, i.e. (u,v,w)⊢(u2,v/2,w);
b odd: xb=x⋅xb−1, i.e. (u,v,w)⊢(u,v−1,uw).
Every operation keeps numbers to O(logp) bits, and there are O(log2p) multiplications/squarings. Multiplying logp-bit numbers costs O(logploglogp) via the Schönhage–Strassen algorithm. Total: O(log3p⋅loglogp) operations.
Corollary
Primes∈NP∩coNP.
Primes∈NP: a Pratt certificate (the generator x + recursive factor proofs) is a short, polynomially-checkable witness of primality.
Primes∈coNP: a factor is a short witness of compositeness.
Historical note. This NP∩coNP result long predates the unconditional AKS algorithm (2002), which finally showed Primes∈P deterministically. But the randomized tests (Miller–Rabin, Solovay–Strassen) remain the practical choice — another instance of randomness winning on efficiency.
Recurring themes to carry into the rest of the course
Theme
Where it appeared
Fingerprinting (test a big identity via a small random/modular projection)
§1 primes, §5–8 matrix product
One-sided error (yes-instances never lie; no-instances err with small prob.)
§1, §5 — these are RP/coRP-style algorithms
Probability amplification by independent repetition
§1, §3 min-cut, §5 Freivalds
Indicator variables + linearity of expectation
§4 QuickSort
Polynomial / Schwartz–Zippel (“a nonzero low-degree polynomial has few roots”)
§5–8
Derandomization (bound the bad set, then pick deterministically)
§6 Cauchy, §7
Guess-and-verify / short certificates (nondeterminism)
§7–9, Pratt
The single sentence that ties them all together:
A small amount of randomness lets us probe a large object so that any “flaw” is almost surely exposed — and when we can describe where the flaws can hide, we can often remove the randomness altogether.