Use randomness to make an algorithm simpler, faster, or possible at all. The recurring theme: an adversary can construct a bad input for a deterministic algorithm, but cannot predict your coin flips. Hashing and verification are in Randomized Hashing and Verification, sampling and sketches in Sampling and Streaming, color coding and random-walk SAT in Randomized Search, heuristics in Heuristic Optimization.
| Why randomness helps | Example |
|---|---|
| defeats adversarial input | random pivot in quicksort; a random hash base |
| avoids worst cases without analysis | treaps instead of red-black trees |
| breaks symmetry | leader election, Karger’s contraction |
| samples instead of enumerating | Monte Carlo integration |
| finds witnesses fast | Miller–Rabin: most bases are witnesses |
| simplifies the code | randomized incremental geometry |
Las Vegas and Monte Carlo
| Las Vegas | Monte Carlo | |
|---|---|---|
| output | always correct | may be wrong with probability |
| running time | a random variable | deterministic (or bounded) |
| guarantee | ”correct, probably fast" | "fast, probably correct” |
| failure mode | runs long (TLE) | wrong answer (WA) |
| complexity class | ZPP | RP / co-RP (one-sided), BPP (two-sided) |
| examples | quicksort, quickselect, Pollard’s rho, Welzl, Seidel’s LP, treaps, randomized incremental Delaunay, hash tables with rehashing | Miller–Rabin, Karger, Freivalds, string hashing, Tutte matrix test, Monte Carlo integration (two-sided, with an error bar), MCTS; simulated annealing has no guarantee at all |
| convert | stop after a time budget and output anything: Monte Carlo | repeat until a verifier accepts: Las Vegas, (Pollard’s rho: a random walk whose output is checked by division) |
One-sided error is the useful kind. If one answer is always right (Miller–Rabin’s “composite”, Freivalds’ and hashing’s “different”), independent repetitions push the error to ; recognising which side is certain tells you where to add verification.
| Per-run error | Runs | Total error |
|---|---|---|
| 20 | ||
| 60 | ||
| (Miller–Rabin per base) | 30 |
Rule of thumb: aim for an error below per submission, far below the probability of a hardware fault, for a handful of extra iterations.
| In contests | Safe? |
|---|---|
| Las Vegas (randomized quicksort, treap) | yes: always correct |
| hashing with a time-seeded base | yes: collision probability about |
| fixed-seed hashing or shuffling | no: hackable (Codeforces has anti-tests for common seeds) |
| Miller–Rabin with the deterministic 64-bit bases | yes: provably correct |
| Monte Carlo with error | yes in practice |
| simulated annealing on an exact-answer problem | no |
| randomized algorithm on an interactive problem or a reproducibility-checking judge | read the statement |
| Class | Meaning |
|---|---|
| ZPP | Las Vegas, expected polynomial time |
| RP | one-sided error: never a false “yes” |
| co-RP | one-sided the other way |
| BPP | two-sided error |
| PP | error (much weaker; contains NP) |
; whether is open but widely believed: randomness is expected to add convenience, not power. See Complexity Theory.
Las Vegas, carefully. Every output is valid; analyse the expected work over the random choices for every fixed legal input. Expected linear time is not a deadline; a heuristic that may silently fail is not Las Vegas merely because it retries; a retry limit changes the guarantee unless exhaustion is handled. Keep correctness and termination arguments separate (randomized pivots change quicksort’s running time, never the correctness of partitioning). Monte Carlo, carefully. Identify the random choices, state the failure bound, and union-bound over all comparisons or queries ( events of error give ). A fixed seed exposed to an adaptive adversary breaks the probability model, and two hashes are independent only if their randomness is; “large modulus” alone is not a proof.
Random numbers and shuffling
mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count() ^ (ull)new char);
ll randInt(ll l, ll r) { return uniform_int_distribution<ll>(l, r)(rng); }
template<class T> void fisherYates(vector<T>& v) { // what std::shuffle(all(v), rng) does
for (int i = sz(v) - 1; i > 0; i--) swap(v[i], v[randInt(0, i)]);
}
ll quickselect(vector<ll> a, int k) { // k-th smallest (0-based), expected O(n)
int l = 0, r = sz(a) - 1;
while (true) {
if (l == r) return a[l];
ll p = a[randInt(l, r)];
int i = l, j = r, m = l; // 3-way partition: < p | == p | > p
while (m <= j) { if (a[m] < p) swap(a[i++], a[m++]); else if (a[m] > p) swap(a[m], a[j--]); else m++; }
if (k < i) r = i - 1; else if (k > j) l = j + 1; else return p;
}
}Never use a fixed seed,
rand(),random_shuffleorsrand(time(0))A fixed seed is predictable and hackable.
rand()is low quality (weak low bits) andrand() % nis biased when does not divideRAND_MAX + 1.random_shuffleusedrand()and was removed in C++17.srand(time(0))has one-second granularity: submissions in the same second share a seed. Seed from the clock, XOR an address in for extra entropy. The common shuffle bugswap(v[i], v[rand() % n])(full range at every step) is not uniform.
| What shuffling protects | Killer input without it |
|---|---|
| quicksort with the first element as pivot | already sorted: |
| Welzl’s enclosing circle | points ordered so each is outside: |
| Seidel’s LP, randomized incremental Delaunay | adversarial insertion order |
| Kuhn’s matching | adversarial adjacency order: shuffling adjacency lists is a cheap real speed-up against anti-Kuhn tests |
| hash tables | colliding keys: per operation |
| unbalanced BSTs | sorted insertion: a linked list |
Proof: Fisher–Yates is uniform, and quickselect is expected linear
Fisher–Yates. Step (from down to 1) chooses uniformly which of the remaining elements ends at position ; the choices are independent. So each of the choice sequences has probability , and distinct sequences give distinct permutations (position ‘s element is determined by step ): every permutation has probability . The buggy version has equally likely sequences, and does not divide for , so it cannot be uniform.
Quickselect. Call a round good if the pivot’s rank lies in the middle half of the current range; this happens with probability , and then the range shrinks to at most of its size. The expected number of rounds while the size is in is at most 2, each costing , so the expected total is . It is Las Vegas: the answer is always correct. Checked: shuffle frequencies of all permutations pass a chi-square test, and quickselect agrees with sorting on random arrays.
Probability tools
| Tool | Statement |
|---|---|
| linearity of expectation | , no independence needed |
| union bound | : crude but almost always enough |
| Markov | : |
| Chebyshev | |
| Chernoff | independent , , : , , so |
| backwards analysis | ”what is the probability that the last element added was important?”: clean expected bounds for randomized incremental algorithms (Seidel’s LP, Welzl, Delaunay) |
Chernoff is what licenses “with high probability”: a sum of independent bounded variables is very close to its mean.
Proof: Markov, Chebyshev, Chernoff and a backwards-analysis example
Markov. pointwise; take expectations. Chebyshev. Markov applied to .
Chernoff. For and , convexity gives , so with ; by independence . Markov on gives ; with this is . Since , the exponent satisfies for . The lower tail is the same computation with and .
Backwards analysis example. Insert distinct numbers in random order and count how often the running minimum changes. The -th inserted element is the minimum of the first with probability (any of them is equally likely to be last), so the expected number of changes is . Welzl and Seidel use the same argument: the last inserted constraint is “important” (defines the answer) with probability , so expensive recomputation is rare.
Derandomization
| Method | Idea |
|---|---|
| conditional expectations | fix the random choices one at a time, always taking the branch whose conditional expectation stays at least the target |
| pairwise independence | many analyses need only pairwise independence: random bits, which can be enumerated |
| fixed witness sets | Miller–Rabin with 7 fixed bases (or the first 12 primes) is deterministic for all 64-bit inputs: Primality and Factorization |
Usually not worth it in practice, but conditional expectations is a genuine proof and construction technique. Example: a random side for every vertex cuts each edge with probability , so some cut has at least edges; fixing vertices greedily finds one deterministically.
vector<int> halfCut(int n, const vector<pair<int, int>>& edges) { // >= m/2 cut edges (no self-loops), O(n + m)
vector<vector<int>> adj(n); for (auto [u, v] : edges) adj[u].push_back(v), adj[v].push_back(u);
vector<int> side(n, -1);
for (int v = 0; v < n; v++) { // put v opposite to the majority of its placed neighbours
int c0 = 0, c1 = 0;
for (int u : adj[v]) if (side[u] == 0) c0++; else if (side[u] == 1) c1++;
side[v] = c0 >= c1 ? 1 : 0;
}
return side;
}Proof: the conditional-expectation cut has at least m/2 edges
Let be the expected number of cut edges when the unplaced vertices are coloured at random. Initially . Placing settles the edges from to already placed neighbours; edges to unplaced vertices stay cut with probability either way. Putting on the side opposite the majority cuts at least half of the settled edges, which is at least their expected contribution, so never decreases. At the end nothing is random and the cut has edges. Checked on random graphs.
Randomized algorithms worth knowing
| Algorithm | Randomness used for | Note |
|---|---|---|
quicksort, nth_element | pivot | Sorting |
| treap, skip list | priorities, levels | Treaps, Data Structure Catalog |
| Miller–Rabin, Pollard’s rho | witnesses, the pseudo-random walk | Primality and Factorization |
| Karger, Karger–Stein | random edge contraction | Global Min Cut |
| Welzl, Seidel’s LP | insertion order | Minimum Enclosing Circle, Linear Programming |
| string hashing, Zobrist and set hashing | the base, random weights | Hashing and Verification |
| Tutte matrix matching | matrix entries | General Matching |
| Freivalds’ check, Schwartz–Zippel | test vectors / points | Hashing and Verification |
| reservoir sampling, sketches | which item to keep, hash functions | Sampling and Streaming |
| color coding, random-walk SAT | random colours, random flips | Randomized Search |
| simulated annealing, MCTS | move acceptance, playouts | Heuristic Optimization, Game Search |
When randomness is not allowed (some interactive or hacking formats, reproducibility-checking judges), read the statement; otherwise randomize by default: it costs one line and removes a whole category of failure.