G27
Self-checkedTier 1 12 min readalgo.hashing-basics

Hashing: functions and collisions

Hash tables as a dictionary with expected constant time: direct addressing, hash functions and the table size, the division and multiplication methods and why the choice of m matters, string hashing, universal hashing, the load factor, why collisions are unavoidable and appear far sooner than expected (the birthday paradox).

Why it exists

Searching an unsorted array takes Θ(n)\Theta(n) and searching a sorted array takes Θ(log⁡n)\Theta(\log n), but an array indexed by the key itself takes Θ(1)\Theta(1): look at position kk. Hashing keeps that speed for keys that are not small integers (names, long numbers, strings) by turning the key into an array index with a hash function. The expected cost of search, insert and delete is then constant, which is why hash tables are the default dictionary of most programming languages. The price: two keys can get the same index (a collision), and the order of the keys is lost.

Prerequisites

You need arrays with constant-time access by index (arrays).

Precise definitions

Dictionary. A set of keys (with attached data) supporting insert, search and delete.

Universe and table. The keys come from a universe UU that is usually huge (UU = all 32-bit numbers, all strings). The table is an array T[0..m−1]T[0..m-1] of mm slots (buckets), with m≪∣U∣m \ll |U|.

Direct-address table. If U={0,…,u−1}U = \{0, \ldots, u-1\} is small, store the record of key kk in T[k]T[k]. All three operations take Θ(1)\Theta(1) time, but the space is Θ(u)\Theta(u), hopeless when u=264u = 2^{64} and only a few thousand keys are present.

Hash function. A function h:U→{0,1,…,m−1}h : U \to \{0, 1, \ldots, m-1\}. The key kk is stored in (or searched at) slot h(k)h(k). It must be deterministic (the same key always gives the same value) and fast.

Collision. Two different keys k1≠k2k_1 \ne k_2 with h(k1)=h(k2)h(k_1) = h(k_2). Since ∣U∣>m|U| > m, collisions cannot be avoided for all inputs (pigeonhole): among any m+1m + 1 distinct keys at least two collide.

Load factor. α=n/m\alpha = n/m for nn keys stored in mm slots. It is the average number of keys per slot.

Simple uniform hashing assumption (SUHA). Each key is equally likely to hash to any of the mm slots, independently of the other keys. Almost all average-case results on hashing are proved under this assumption; it is what a good hash function tries to imitate.

How it works

Collisions come early

By pigeonhole a collision is certain after m+1m + 1 keys. But it is likely much sooner. Hash kk keys independently and uniformly into mm slots. The probability that no two collide is P(no collision)=∏i=0k−1(1−im)≈e−k(k−1)/(2m),P(\text{no collision}) = \prod_{i=0}^{k-1} \left(1 - \frac{i}{m}\right) \approx e^{-k(k-1)/(2m)}, because the ii-th key must avoid the ii slots already used. The expected number of colliding pairs is (k2)/m\binom{k}{2}/m (each of the (k2)\binom{k}{2} pairs collides with probability 1/m1/m). For m=365m = 365 slots a collision becomes more likely than not with only 2323 keys (the birthday paradox; in general about 1.18m1.18\sqrt m keys), when the table is only 6%6\% full.

Collisions are likely much sooner than expected: start

Computed by a script, not typed
number of keysP(some collision)P(no collision)expected colliding pairs C(k,2)/365
k = 5
k = 10
k = 15
k = 20
k = 23
k = 30
k = 40
k = 50
k = 60
k = 70

Step 0

k keys are hashed independently and uniformly into 365 slots. The exact probabilities are computed with fractions: with only 23 keys a collision is already more likely than not.

0 / 10
computed by script: the quantities are measured by running C, or evaluated, one row at a time. python3 scripts/gen-algo-hash-traces.py

Hash functions

A good hash function spreads the keys of the application evenly, whatever pattern they have. The standard ones for integer keys:

Division method. h(k)=k mod mh(k) = k \bmod m. Fast and simple, but the quality depends on mm. If mm shares a factor with a pattern in the keys, whole buckets stay empty and others overflow. Advice: choose mm a prime not close to a power of 22 (or 1010). Never take m=2pm = 2^p if the keys' low bits are not random, since k mod 2pk \bmod 2^p only looks at the last pp bits.

Multiplication method. h(k)=⌊m (kA mod 1)⌋h(k) = \lfloor m\,(kA \bmod 1) \rfloor for a constant 0<A<10 < A < 1 (Knuth suggests A≈(5−1)/2=0.6180339887…A \approx (\sqrt 5 - 1)/2 = 0.6180339887\ldots): multiply the key by AA, keep the fractional part, multiply by mm and take the integer part. The value of mm is not critical, so mm can be a power of two, which makes the computation a multiplication and a shift on machine words. For k=1234k = 1234 and m=100m = 100: kA=762.6…kA = 762.6\ldots, fractional part 0.65…0.65\ldots, so h(k)=65h(k) = 65.

Other ideas. Mid-square: square the key and take the middle digits. Folding: cut the key into pieces and add them. Strings: treat the characters as digits of a number in some base BB and reduce by Horner's rule, h=(⋯((s0B+s1)B+s2)⋯ ) mod mh = (\cdots((s_0 B + s_1) B + s_2) \cdots) \bmod m, so that all characters, in order, influence the result.

Universal hashing. Any single fixed function has a bad set of keys (an adversary can choose keys that all collide). Choosing the function at random from a family at the start defeats this. For a prime p>∣U∣p > |U|, the family ha,b(k)=((ak+b) mod p) mod mh_{a,b}(k) = ((ak + b) \bmod p) \bmod m with random a∈{1,…,p−1}a \in \{1, \ldots, p - 1\} and b∈{0,…,p−1}b \in \{0, \ldots, p - 1\} has the property that for any two different keys the probability (over the choice of a,ba, b) that they collide is at most 1/m1/m (checked exhaustively on small cases), so the expected cost is as for SUHA whatever the keys are.

What the choice of mm does. The program hashes the twenty keys 10,20,…,20010, 20, \ldots, 200 (multiples of 1010, a typical pattern) with several mm and counts how many buckets are used and how large the largest bucket is.

#include <stdio.h>
#include <math.h>
 
#define N 20
 
/* the keys are 10, 20, ..., 200: a pattern such as real keys often have (multiples of a round number) */
static void report(const char *name, int m, int (*h)(int, int)) {
    int load[64] = {0}, used = 0, max = 0;
    for (int i = 1; i <= N; i++) load[h(10 * i, m)]++;
    for (int b = 0; b < m; b++) {
        if (load[b] > 0) used++;
        if (load[b] > max) max = load[b];
    }
    printf("%-15s m = %2d  buckets used = %2d  largest bucket = %2d\n", name, m, used, max);
}
 
static int division(int key, int m) { return key % m; }
 
static int multiplication(int key, int m) {
    double a = 0.6180339887498949, x = key * a;      /* A = (sqrt(5) - 1) / 2 */
    return (int)(m * (x - floor(x)));
}
 
int main(void) {
    report("division", 10, division);
    report("division", 11, division);
    report("division", 16, division);
    report("division", 13, division);
    report("multiplication", 16, multiplication);
    printf("\nprobability that k keys, hashed uniformly into 365 slots, have a collision:\n");
    int ks[4] = {10, 23, 30, 50};
    for (int t = 0; t < 4; t++) {
        double none = 1.0;
        for (int i = 0; i < ks[t]; i++) none *= 1.0 - i / 365.0;
        printf("k = %2d  %.4f\n", ks[t], 1.0 - none);
    }
    return 0;
}
division        m = 10  buckets used =  1  largest bucket = 20
division        m = 11  buckets used = 11  largest bucket =  2
division        m = 16  buckets used =  8  largest bucket =  3
division        m = 13  buckets used = 13  largest bucket =  2
multiplication  m = 16  buckets used = 13  largest bucket =  2
 
probability that k keys, hashed uniformly into 365 slots, have a collision:
k = 10  0.1169
k = 23  0.5073
k = 30  0.7063
k = 50  0.9704

Spreading the keys 10, 20, ..., 200 over a table: start

Computed by a script, not typed
hash functionbuckets used (of m)empty bucketslargest bucketaverage load 20 / m
division, m = 10
division, m = 11
division, m = 16
division, m = 13
multiplication, m = 16

Step 0

Twenty keys that are multiples of 10 are hashed by key mod m for four table sizes and by the multiplication method. A good function uses every bucket and keeps the largest one small.

0 / 5
computed by script: the quantities are measured by running C, or evaluated, one row at a time. python3 scripts/gen-algo-hash-traces.py

With m=10m = 10 every key lands in bucket 00: the table degenerates into one list. With m=16m = 16 only even buckets are used (the factor 22 of the keys is shared). Primes 1111 and 1313 spread the keys well. The multiplication method copes even with m=16m = 16.

Resolving collisions

Because collisions happen, a hash table needs a rule for keys that share a slot: chaining (each slot holds a list of keys) or open addressing (a colliding key is put into another slot of the table, found by a probe sequence). They are the subject of the next page; the expected cost as a function of the load factor is in load factor and expected probes.

What a hash table cannot do well: keep keys in sorted order, find the next larger key, or report all keys in a range. A search tree does those in O(log⁡n)O(\log n); a hash table needs Θ(n)\Theta(n) time.

Worked examples

EX 1Hash five keys with the division method

Easy

m=10m = 10, h(k)=k mod 10h(k) = k \bmod 10 (the last digit): 123→3123 \to 3, 456→6456 \to 6, 789→9789 \to 9, 1011→11011 \to 1, 1213→31213 \to 3. The keys 123123 and 12131213 collide in bucket 33. With m=7m = 7 the buckets would be 123 mod 7=4123 \bmod 7 = 4, 456 mod 7=1456 \bmod 7 = 1, 789 mod 7=5789 \bmod 7 = 5, 1011 mod 7=31011 \bmod 7 = 3, 1213 mod 7=21213 \bmod 7 = 2: no collision this time; whether there is one depends on both the keys and mm.

EX 2How many keys until a collision is certain, and likely?

Easy

In a table with m=100m = 100 slots, 101101 keys force a collision (pigeonhole): the maximum number of keys that can be stored without any collision is m=100m = 100. A collision becomes more likely than not after about 1.18100≈121.18 \sqrt{100} \approx 12 keys. The expected number of colliding pairs for kk random keys is (k2)/m\binom{k}{2}/m: for k=23k = 23 and m=365m = 365 it is 253/365=0.69253/365 = 0.69.

EX 3Bad table size

Medium

A system hashes record numbers that are always multiples of 88 with h(k)=k mod 16h(k) = k \bmod 16. Only the slots 00 and 88 can ever be used, whatever the number of records: the table behaves as if it had 22 slots. With a prime such as m=17m = 17 the multiples of 88 are spread over all 1717 slots (since gcd⁡(8,17)=1\gcd(8, 17) = 1, the residues of 8,16,24,…8, 16, 24, \ldots cycle through all of them).

EX 4The multiplication method by hand

Medium

A=0.618…A = 0.618\ldots, m=100m = 100. For k=5678k = 5678: kA=3509.2…kA = 3509.2\ldots, fractional part 0.19…0.19\ldots, h=⌊100⋅0.19⌋=19h = \lfloor 100 \cdot 0.19 \rfloor = 19. For k=1234k = 1234 the result is 6565 (above). Two keys that are close together (12341234 and 12351235) go to far-apart slots, because multiplying by AA scatters them: this is the desired behaviour, unlike the division method with a power-of-two modulus, where neighbouring keys go to neighbouring slots.

EX 5Counting collisions

GATE level

(a) nn keys are hashed into mm slots with h(k)=k mod mh(k) = k \bmod m; the keys are 1,2,…,1001, 2, \ldots, 100 and m=10m = 10. Every bucket receives exactly 1010 keys (the last digit repeats every 1010 keys): no bucket is empty but every bucket has a chain of 1010. (b) What is the smallest number of keys that guarantees a collision in a table of mm slots? m+1m + 1. (c) What is the load factor of a table with 20002000 keys in 800800 slots? α=2.5\alpha = 2.5, possible for chaining (average chain 2.52.5) but impossible for open addressing. (d) A hash function sends every key to slot 00. It is a legal function and the table works, but every operation costs Θ(n)\Theta(n): correctness does not depend on the quality of hh, only speed does.

Cheat box

Cheat box

  • Direct addressing: Θ(1)\Theta(1) but space Θ(∣U∣)\Theta(|U|). Hash table: mm slots, h:U→{0,…,m−1}h : U \to \{0, \ldots, m-1\}, load factor α=n/m\alpha = n/m.
  • Collision: h(k1)=h(k2)h(k_1) = h(k_2), k1≠k2k_1 \ne k_2; unavoidable (m+1m + 1 keys force one) and likely early (birthday: ≈1.18m\approx 1.18\sqrt m keys, 2323 for 365365). Expected colliding pairs (k2)/m\binom{k}{2}/m.
  • Division: k mod mk \bmod m, mm a prime not near a power of 22. Multiplication: ⌊m(kA mod 1)⌋\lfloor m (kA \bmod 1) \rfloor, A≈0.618A \approx 0.618, any mm.
  • SUHA: each key equally likely in each slot, independently. Universal hashing: random hh from a family, collision probability ≤1/m\le 1/m for any two keys.
  • Correctness never depends on hh; only the running time does. A hash table does not keep order.

Traps and GATE patterns

Connections

Searching by hashing is compared with binary search (needs order) and with binary search trees (BST). The two ways to handle collisions are in chaining and open addressing and their costs in load factor and expected probes. Using the key as an array index is also the idea behind counting sort.

PYQs

3 previous year questions from your book. I re-solved each one myself (2 by running or simulating, 1 by reasoning only); the book's key is shown next to my answer. All PYQs

GATE 2023 · Set 1Q4 · page 88 of the book
An algorithm has to store several keys generated
by an adversary in a hash table. The adversary is
malicious who tries to maximize the number of
two simple uniform hash functions h1 and h2.
Further suppose our hashing scheme uses h1 for the
odd keys and h2 for the even keys. What is the
expected number of keys in a slot?
  • (a)m/n
  • (b)n/m
  • (c)2n/m
  • (d)n/2m
GATE 2021 · Set 1Q6 · page 88 of the book
Consider a dynamic hashing approach for 4-bit
integer keys:
1. There is a main hash table of size 4.
2. The 2 least significant bits of a key is used to
index into the main hash table.
3. Initially, the main hash table entries are empty.
4. Thereafter, when more keys are hashed into it, to
resolve collisions, the set of all keys corresponding
to a main hash table. entry is organized as a binary
tree that grows on demand.
5. First, the 3rd least significant bit is used to divide
the keys into left and right subtrees.
6. To resolve more collisions, each node of the
binary tree is further sub-divided into left and right
subtrees based on the 4th least significant bit.
DATA STRUCTURE

7. A split is done only if it is needed, i.e., only
when there is a collision.

Consider the following state of the hash table.

Which of the following sequences of key
insertions can cause the above state of the hash
table (assume the keys are in decimal notation)?
  • (a)5,9,4,13,10,7
  • (b)9,5,10,6,7,1
  • (c)10,9,6,7,5,13
  • (d)9, 5,13,6,10,14
GATE 2015 · Set 2Q10 · page 89 of the book
Which one of the following hash functions on
integers will distribute keys most uniformly over 10
buckets numbered 0 to 9 for i ranging from 0 to 2020?
  • (a)h(i)= i2 mod 10
  • (b)h(i)= i3 mod 10
  • (c)h(i)=(11*i2) mod 10
  • (d)h(i)=(12*i2) mod 10

Self-check

Question 1

How many keys must be inserted into a table of 5050 slots to guarantee at least one collision?

Show answer

5151 (pigeonhole).

Question 2

Why is h(k)=k mod 16h(k) = k \bmod 16 a poor function for keys that are multiples of 44?

Show answer

k mod 16k \bmod 16 takes only the values 0,4,8,120, 4, 8, 12 for such keys: at most 44 of the 1616 slots are used.

Question 3

State the simple uniform hashing assumption.

Show answer

Each key is equally likely to hash to each of the mm slots, independently of where the other keys hash.

Question 4

Can a hash table keep its keys sorted?

Show answer

No: hashing destroys the order of the keys. Finding the minimum or the next larger key costs Θ(n)\Theta(n).

Revision card

One-screen revision

  • h:U→{0..m−1}h : U \to \{0..m-1\}; load factor α=n/m\alpha = n/m; collision unavoidable (m+1m + 1 keys).
  • Birthday: collision likely after ≈1.18m\approx 1.18\sqrt m keys; expected colliding pairs (k2)/m\binom{k}{2}/m.
  • Division k mod mk \bmod m (mm prime); multiplication ⌊m(kA mod 1)⌋\lfloor m (kA \bmod 1) \rfloor; strings by Horner; universal hashing.
  • Expected O(1)O(1) under SUHA with constant α\alpha; worst case Θ(n)\Theta(n); no order.

References

  • ·Cormen, Leiserson, Rivest, Stein, Introduction to Algorithms (3rd edition), Chapter 11 Hash Tables (11.1 direct-address tables, 11.2 hash tables, 11.3 hash functions)
  • ·Sedgewick and Wayne, Algorithms (4th edition), Section 3.4 Hash Tables
  • ·Knuth, The Art of Computer Programming, Volume 3, Section 6.4 Hashing

Verification

The spread of the keys over buckets was measured by the C program on this page and recomputed in Python. The birthday probabilities are exact (Fractions) and the program's floating-point output matches them to four decimals; 23 keys is the smallest number with a collision probability above one half. The expected number of colliding pairs C(n,2)/m and the collision probability were verified by enumerating every one of the m^n assignments for small m and n. The statement that the family ((ak + b) mod p) mod m collides with probability at most 1/m was checked exhaustively for eight pairs (p, m). The multiplication and string examples were recomputed. The advice on the choice of m (a prime not close to a power of two) is the standard textbook advice and is illustrated, not proved. Textbook chapter references are from memory. SECOND PASS (2026-11-02, done by the assistant, not a human check): every Self-check question was solved before the printed answer was read and all agreed; the definitions, worked examples, cheat box and traps were read claim by claim and the numbers re-derived by hand or by a small script (loop counts, recurrences, merge and quicksort counts and averages, hash probes and load-factor formulas, DP tables, MST and shortest-path runs, Floyd matrices); long C programs were not re-read line by line (they are compiled and compared by npm run verify:c, and their printed outputs were checked against the prose); tables and animations are machine output and were read, not re-run; No other defect found. Status raised to self-checked; verified needs a textbook or human check.

last verified: never