Intuition What this page does
The parent note states that expected search cost is O ( 1 + α ) . Here we build that number from nothing , one picture at a time. By the last figure you will have seen every term of E [ X ] ≤ m n − 1 appear on the page. No symbol is used before it is drawn.
We start with zero notation. We will earn each piece.
Definition The picture we are counting inside
A hash table is just a row of numbered boxes — call them slots . We label them 0 , 1 , 2 , … , m − 1 , so there are m of them in total. (m is simply how many boxes we have. )
A key is a thing we want to store (a number, a name). A hash function h is a rule that reads a key and points at exactly one box: h ( key ) = a slot number.
Look at the figure. Three keys (x , y 1 , y 2 ) each get an arrow into a box. Two of them landed in the same box — that shared box is a collision . Collisions are the enemy: a box with several keys forces us to walk down a little list (a chain ) to find ours.
Small X means fast lookup. So the whole page is: find the typical size of X .
Intuition WHY we cannot just "assume keys spread out"
An adversary — think of a bully — is allowed to pick the keys x , y 1 , y 2 , … on purpose to jam one box. If our rule h is fixed and public, the bully computes which keys collide and hands us exactly those. Every lookup becomes a slow walk down one giant chain.
The fix, drawn below: we roll dice to choose h from a whole bag of hash functions (a family H ), and we roll after the bully has committed to the keys — and secretly.
Common mistake The trap this figure kills
"Random hashing = each key lands in a uniformly random box." No. The keys are frozen and possibly evil. The only random thing on the whole page is which h we pulled out of the bag . Read every probability below as: keys fixed, function random.
This is why we can beat any input: the bully cannot aim at randomness he has not seen. See Adversarial inputs and randomized algorithms .
Definition Universal family (the promise our bag makes)
Our bag H is called universal if, for any two different keys x and y you name in advance, a randomly pulled h makes them collide only rarely:
Pr h ∈ H [ h ( x ) = h ( y ) ] ≤ m 1
Pr [ ⋯ ] ::: "what fraction of the functions in the bag" do the thing inside.
h ( x ) = h ( y ) ::: the event "these two keys land in the same box".
m 1 ::: one box out of m — the collision odds you'd get from pure luck if y 's box were chosen fairly at random.
1/ m is exactly the right target
If y 's box were a fair spinner over m boxes, the chance it matches x 's box is 1/ m . A universal family promises collisions are no worse than that fair spinner , for every pair the adversary could name. That is the strongest thing we could reasonably ask for.
Definition Where the tiny wrinkle comes from — meet the prime
p
To build an actual universal bag, the standard recipe (parent note) first stretches every key through a large prime number p — a whole number, bigger than any key, divisible only by 1 and itself (see Modular arithmetic and primes ). The rule is h ( k ) = ( ( ak + b ) mod p ) mod m : first fold the key down into the range 0.. p − 1 using p , then squeeze into our m boxes.
p ::: the big prime "workbench" the recipe computes on — a fixed, publicly known number, not the number of boxes.
The final mod m ::: the last squeeze into the m real boxes.
WHY ≤ and not = ? Those p intermediate values get chopped into m boxes. Unless m divides p evenly (m ∣ p ), some boxes catch one more value than others, so collisions can be a hair above 1/ m . The honest bound is ≤ m 1 + p 1 ; since p is astronomically large, the extra p 1 is invisible. On this page we simply use the clean bound ≤ m 1 .
Intuition WHY we introduce a switch variable
Counting X directly is awkward — the collisions are tangled together (if three keys pile up, they all depend on the same random h ). The trick that untangles everything: replace the messy count with a sum of tiny switches , one switch per other key.
Definition The indicator switch
For each other key y = x , define a switch X x y :
X x y = { 1 0 if h ( x ) = h ( y ) ( collision — switch ON ) otherwise ( no collision — switch OFF )
Then the total traffic jam is just the switches added up:
X = ∑ y = x X x y
X x y ::: is this one particular key stepping on x ? Yes = 1 , No = 0 .
∑ y = x ::: add over every other key in the table.
The figure shows a row of light bulbs, one per key. Lit bulbs (value 1 ) are the collisions; counting lit bulbs = the value of X . Nothing clever yet — we just renamed the count. The payoff comes next.
Intuition WHY this is the whole reason we used switches
Expectation of a switch is its probability. So Step 3's universal promise — a statement about probability — becomes a statement about averages , and averages are things we can add up . That adding is Step 6.
Common mistake The subtle point this step rests on
Collisions are correlated — the same random h decides all of them at once, so the switches are not independent. Almost every averaging rule breaks under dependence. Linearity of expectation is the rare rule that does not care : E [ A + B ] = E [ A ] + E [ B ] always, dependent or not. That is why the whole derivation works.
α = m n ( keys per box, on average )
n ::: how many keys are stored.
m ::: how many boxes.
α ::: how crowded the table is. α = 0.5 means "half a key per box".
Combine with Step 6:
avg others in x ’s box E [ X ] ≤ m n − 1 < m n = α ⇒ walk the chain expected search = 1 + E [ X ] = O ( 1 + α )
The + 1 is x itself (we always touch our own box). See Load factor and rehashing .
Intuition The finish line
Keep the table roughly as big as the data, m = Θ ( n ) . Then α = n / m is a constant , so every lookup costs O ( 1 + α ) = O ( 1 ) on average — for every possible input , adversary included. The guarantee is over our dice , never over lucky data.
Worked example All the edge cases, one by one
n = 0 or n = 1 ::: no other keys, so ∑ y = x is an empty sum = 0 . E [ X ] = 0 , cost = 1 . The formula m n − 1 gives ≤ 0 — consistent (an "at most" of 0 ).
x already inserted ::: then x is one of the n keys, so only n − 1 others can collide — exactly the m n − 1 we derived.
x not yet inserted ::: all n stored keys are "others", so use m n = α . (One larger, negligible difference.)
α ≫ 1 (overloaded table) ::: the bound still holds — cost is O ( 1 + α ) , which is now large . Universal hashing does not magically fix an under-sized table; it fixes the adversary , not the load . Cure the load by rehashing into a bigger m .
m ∤ p (boxes don't split the prime evenly) ::: boxes slightly uneven; bound loosens to m 1 + p 1 per pair (Step 3's prime p ). Since p is enormous, p 1 is invisible. Guarantee survives.
One flow, left to right: random h → per-pair collision ≤ m 1 → switch X x y with average ≤ m 1 → add n − 1 of them via linearity → E [ X ] ≤ m n − 1 → cost O ( 1 + α ) .
Recall Feynman: the whole walk in plain words
We have a wall of numbered boxes and we want to drop our key into one and later find it fast. Trouble: a bully picks keys on purpose to jam one box. Our escape is to roll dice and pick our sorting-rule from a bag — and we roll secretly, so the bully can't aim.
The bag is "fair" (universal) if any two keys the bully names only crash into the same box about one time in m . Now, to count how many keys crash into our box, we put a light bulb on every other key: lit if it crashes into us, dark otherwise. The number of lit bulbs is our slowdown. The average brightness of one bulb is just its crash chance, ≤ m 1 . And here's the magic: the average of the whole wall of bulbs is just the sum of each bulb's average — this is true even though all the bulbs are wired to the same dice. Add up n − 1 bulbs at m 1 each and you get at most m n − 1 . Keep the wall about as wide as the pile of keys and that number is a constant — so every lookup is fast, no matter what the bully does.
Roll the FUNCTION, freeze the DATA. Bulbs add even when wired together. E [ X ] ≤ m n − 1 .
Roll dice pick h from bag
Pair collides at most 1 over m
Switch Xxy average at most 1 over m
E of X at most n-1 over m
Search cost O of 1 plus alpha
Constant time every input