Exercises — Hash table — structure, open addressing vs chaining
Before we start, let us pin down the two symbols used everywhere below, so no notation appears un-earned:
Level 1 — Recognition
L1.1 — Load factor
Problem. A hash table has capacity and currently stores keys. What is its load factor ? Would open addressing still be allowed to operate here?
Recall Solution
WHAT we did: plugged into the definition of load factor. WHY it matters: open addressing stores every key inside the array, so it needs at least one free slot — it only works while . Here , so it operates, but it is already above the usual rehash threshold (), so a good implementation would rehash to a bigger array right about now (see Load factor and dynamic resizing / rehashing).
L1.2 — Name the mechanism
Problem. In each scenario, name whether it describes chaining or open addressing:
(a) Bucket 3 holds a linked list [19, 42, 8].
(b) The array is [_, _, 12, 22, 17] and 22 sits in slot 3 because slot 2 was taken.
Recall Solution
(a) Chaining — multiple keys hang outside the array in a list at one bucket. (See Linked lists.) (b) Open addressing — all keys live inside the flat array; 22 slid to the next slot by probing. Mnemonic: CHAIN out, PROBE in.
Level 2 — Application
L2.1 — Chaining insert & search count
Problem. With and , insert 9, 14, 24, 19, 3 in that order using separate chaining. Show every bucket's list. Then: how many list-nodes must a search for 24 examine?
Recall Solution
Compute each home slot (), appending to the tail of that bucket's list:
9 % 5 = 4→ bucket 4:[9]14 % 5 = 4→ bucket 4:[9, 14](collision → chain it)24 % 5 = 4→ bucket 4:[9, 14, 24]19 % 5 = 4→ bucket 4:[9, 14, 19]? No — , append:[9, 14, 24, 19]3 % 5 = 3→ bucket 3:[3]
Final table:
| Bucket | List |
|---|---|
| 0 | [] |
| 1 | [] |
| 2 | [] |
| 3 | [3] |
| 4 | [9, 14, 24, 19] |
Search 24: go to bucket 4, scan the list front-to-back: 9 (no), 14 (no), 24 (yes) → examined 3 nodes.

L2.2 — Linear probing insert
Problem. With and , insert 8, 15, 22 using linear probing (). Show the array after each insert and give the final array.
Recall Solution
Slot rule: , trying until empty.
8 % 7 = 1→ slot 1 empty → place.[_,8,_,_,_,_,_]15 % 7 = 1→ slot 1 taken → : empty → place.[_,8,15,_,_,_,_]WHY slide right: nudges us one slot along.22 % 7 = 1→ slot 1 taken, slot 2 taken → : empty → place.[_,8,15,22,_,_,_]
Final: [_, 8, 15, 22, _, _, _] (indices 1,2,3 filled). This is a primary cluster — three keys in a contiguous run.

L2.3 — Polynomial string hash
Problem. Using the polynomial rolling hash with base and ASCII codes (, , ), compute , then its index into a table of capacity .
Recall Solution
Treat the string as a base- number, most significant character first:
Compression (turn the huge integer into a valid slot):
WHY base- and not a plain sum: the powers give each position a different weight, so "abc" and "cba" (an anagram) produce different codes — a plain sum would collide them. See Polynomial rolling hash & Rabin–Karp.
Level 3 — Analysis
L3.1 — Expected probes from
Problem. An open-addressed table sits at . Using the uniform-hashing model, how many probes does an unsuccessful search expect? Then: at what does that expectation reach exactly ?
Recall Solution
The model says each probed slot is occupied with probability , so the expected number of probes is the geometric sum
At :
For , solve

L3.2 — Why the tombstone
Problem. Table [_, 8, 15, 22, _, _, _] (from L2.2, ). A student deletes 15 by simply blanking slot 2, giving [_, 8, _, 22, _, _, _]. Now search(22) is run. Trace it and explain the bug and the fix.
Recall Solution
search(22): . Probe:
- : slot 1 holds
8≠ 22 → keep going. - : slot 2 is empty → search concludes "22 is not here" and stops. ✗
But 22 is in slot 3! The blanked slot 2 severed the probe chain — an empty slot is the universal "stop" signal.
Fix: on deletion, write a tombstone (a DELETED marker) instead of a blank. Search treats a tombstone as "keep probing"; insertion treats it as "reusable free slot." With a tombstone in slot 2, search(22) correctly walks 1 → 2 (tombstone, continue) → 3 (found). ✓
Level 4 — Synthesis
L4.1 — Rehash trigger and reinsertion
Problem. An open-addressed table has and rehashes when . Keys are inserted one at a time. (a) After how many inserts does the first rehash trigger? (b) The rehash doubles capacity to ; after reinserting all keys, what is the new load factor?
Recall Solution
(a) Trigger condition: . The first integer crossing this is , giving . So the rehash fires on the 6th insert. (b) All keys are reinserted into the new array of capacity : WHY doubling: halving buys many cheap inserts before the next rehash, so the expensive copy happens rarely — the amortized cost per insert stays .
L4.2 — Choosing a strategy
Problem. You are building a symbol table for a compiler. Keys are identifier strings, and the workload is insert-heavy with frequent deletions and reinsertions as scopes open and close. You cannot predict the final key count. Argue for chaining or open addressing, citing three concrete properties.
Recall Solution
Choose separate chaining. Reasons, each tied to the workload:
- Frequent deletions → chaining deletes by simply unlinking a list node ( given the node), with no tombstones to accumulate and pollute the table. Open addressing would degrade under this churn (see L3.2 trap).
- Unknown final → chaining tolerates gracefully (lists just grow), so an under-sized array is only mildly slow, not broken. Open addressing fails at .
- Load-factor robustness → search stays instead of the sharper blow-up.
Trade-off acknowledged: chaining loses cache-friendliness (pointer chasing) — but for a correctness- and flexibility-driven compiler table that is an acceptable price. This is the CHAIN out, PROBE in decision applied deliberately. See Sets and Maps / Dictionaries.
Level 5 — Mastery
L5.1 — Collision probability (birthday flavour)
Problem. You hash keys uniformly into slots. Give the exact expression for the probability that at least two keys collide, and evaluate it (to 2 decimals) for .
Recall Solution
Compute the complement: the probability of no collision means all keys land in distinct slots. The 1st key is free; the 2nd must avoid 1 taken slot (); the -th must avoid taken slots: Therefore WHY this matters for hashing: with only 23 keys in 365 slots (, a nearly empty table) a collision is already more likely than not. This is the Birthday paradox — the reason collision resolution is mandatory, not a rare afterthought.
L5.2 — Prove tombstone-free deletion for chaining, and bound worst case
Problem. (a) Argue that chaining never needs tombstones. (b) Construct an adversarial input that forces a chained table with buckets into search, and state the load factor at that point.
Recall Solution
(a) In chaining, each bucket is a self-contained list. Deleting a key means unlinking its node; the list's other nodes remain reachable because the list's own pointers are repaired, not a global probe sequence. There is no "chain across the array" to sever — so no stop-signal ambiguity — so no tombstone is ever required. (b) Adversary: pick keys all congruent mod , e.g. for insert (all ). Every key lands in bucket 0, forming one list of length . Searching for the last key scans all nodes → .
- Load factor at , : , yet the worst-case cost is not but the full list length . WHY: is an average over uniform hashing; a pathological hash (or a malicious key stream) defeats the average. The real defence is a good, unpredictable hash function — see Hash functions — properties and design.
Recall One-screen summary of every answer
L1.1: · L1.2: chaining / open addressing.
L2.1: bucket 4 = [9,14,24,19], bucket 3 = [3], search 24 = 3 nodes · L2.2: [_,8,15,22,_,_,_] · L2.3: code , index .
L3.1: probes; at · L3.2: tombstone fixes severed chain.
L4.1: rehash on 6th insert; new · L4.2: chaining.
L5.1: · L5.2: adversary all-same-bucket, , cost .