3.3.6 · D5Hashing

Question bank — Load factor — when to resize, rehashing cost

1,938 words9 min readBack to topic

This is a companion to the parent topic. Before you start, make sure you can state from memory: the load factor ==== (keys over buckets ), and why doubling gives amortized inserts. If either is fuzzy, reread the parent, then come back.

Figure — Load factor — when to resize, rehashing cost
Figure — Load factor — when to resize, rehashing cost
Figure — Load factor — when to resize, rehashing cost
Figure — Load factor — when to resize, rehashing cost


True or false — justify

TF1. "A load factor above 1 always means the hash table is broken."
False. In chaining is the average chain length and can happily exceed 1; only open addressing is capped at because each slot holds at most one key.
TF2. "Doubling the array halves the load factor."
True. ; if stays fixed and , then . That instant drop is exactly why one rehash buys many future cheap inserts.
TF3. "Rehashing lets us skip re-computing hashes — we just copy each bucket to the same index in the bigger array."
False (see Figure 3). The bucket index is ; when changes to the new count , generally differs, so every key must be re-placed. Copying by index would scatter keys to wrong buckets.
TF4. "Amortized per insert means every insert is ."
False. The rehash insert is — genuinely slow. Amortized means the average over a sequence is constant; individual inserts can spike. See Amortized Analysis.
TF5. "If we grow by adding a fixed 100 slots each time, inserts are still amortized — just with a bigger constant."
False (see Figure 1). Additive growth rehashes every 100 inserts, and total move work is , i.e. amortized . Only multiplicative growth gives .
TF6. "A perfect hash function makes the load factor irrelevant."
False. Even with zero collisions, high in open addressing means fewer empty slots to land in, and in chaining it costs memory patterns/cache misses. controls occupancy independent of collision quality. See Hash Functions.
TF7. "Growing at 0.75 and shrinking at 0.74 keeps memory tightest, so it's the best policy."
False. With grow and shrink thresholds nearly touching, a single insert/delete can bounce across both, triggering repeated resizes — thrashing. You need a gap (hysteresis), e.g. grow at 0.75, shrink at 0.25.
TF8. "The probe formula applies to chaining too."
False (see Figure 2 and Figure 4). That bound comes from open addressing, where consecutive full slots form a probe cluster: a search must step past every full slot in the run before it finds an empty one. Chaining has no such run — each bucket owns its own list — so its expected cost is the gentle , not the exploding .
TF9. "Pre-sizing the table to the expected key count is pointless because amortized cost is already ."
False. Amortized still pays total move work over a bulk load; pre-sizing to fit all keys avoids every mid-load rehash, a real constant-factor win. See Dynamic Arrays.

Spot the error

SE1. "Total rehash work when doubling from size 1 to is ."
Error: it's a geometric sum, not terms of size . , which is , not .
SE2. "Open-addressing tables should resize at to save memory, since probes are still finite."
Error (see Figure 2): at the expected unsuccessful probes are . 'Finite' is not 'fast'; the cliff makes 0.7 the practical threshold.
SE3. "Since one rehash costs and we insert keys, total cost is ."
Error: rehashes get exponentially rarer as the table doubles, so their total is , not rehashes of size . Total insert cost is , amortized .
SE4. "After a delete, we should always rehash to keep current."
Error: deletes only lower , which makes lookups faster, not slower. Rehash on delete only when falls below a shrink threshold, and even then respect hysteresis.
SE5. "In open addressing, deleting a key just means setting its slot to empty."
Error (see Figure 4): a plain empty would break the probe chain for other keys that passed through that slot. You need a tombstone (deleted marker), which also inflates effective until a rehash clears them.
SE6. "Choosing guarantees never exceeds forever."
Error: it only holds for the current . Keep inserting and grows past that , so climbs again and a resize is still needed. Pre-sizing delays, not eliminates, resizing.

Why questions

WHY1. Why does chaining tolerate while open addressing resizes near ?
(See Figure 2.) Chaining cost grows linearly as , gentle even past 1; open addressing cost is , which explodes as .
WHY2. Why does multiplicative growth turn total rehash work into a geometric series but additive growth doesn't?
(See Figure 1.) Doubling means each rehash moves twice the previous one, so the sum is dominated by the last term (); additive growth makes each rehash bigger by only a fixed step, giving an arithmetic series that sums to .
WHY3. Why is the expected chain length exactly under uniform hashing?
Each of keys lands in your bucket with probability independently, so the expected count sharing it is .
WHY4. Why can't we cache the old bucket indices to speed up a rehash?
(See Figure 3.) Because the new index depends on the new modulus (the new bucket count), which none of the old indices encode; every key must be recomputed against regardless.
WHY5. In open addressing, the expected unsuccessful-search probes are — why does each term represent an added probe, and why does the sum converge?
(See Figure 2 for the sum.) Probe 1 always happens (weight ). You need probe 2 only if slot 1 was full — probability — so it contributes . You need probe 3 only if slots 1 and 2 were full — probability — contributing ; in general probe carries weight . Because these weights shrink geometrically, so is finite; at they do not shrink and the sum diverges — a full table has no empty slot to stop at.
WHY6. Why do we double instead of, say, ×1.01?
A tiny factor like ×1.01 makes rehashes extremely frequent (every inserts), so the constant behind balloons; the factor must be a fixed number meaningfully above 1 (2 or 1.5) for a small constant.
WHY7. Why do we count 'elements moved' rather than 'slots visited' when totalling rehash cost?
Because re-inserting is proportional to the number of live keys , not the array size ; empty slots cost nothing to move, so is the true work driver.

Edge cases

EC1. What is for an empty table, and does the resize rule misbehave there?
; the grow condition is false, so nothing triggers — correct, an empty table never resizes.
EC2. What happens to the probe formula exactly at in open addressing?
It becomes , undefined — signalling a full table where an unsuccessful search never terminates. This is why open addressing must resize strictly before .
EC3. Starting a table at size 1 and doubling — how many rehashes to reach keys?
About rehashes (at sizes ), each cheaper-then-costlier, summing to total move work.
EC4. If every key hashes to the same bucket, what does tell you about actual performance?
Nothing useful — assumes uniform spreading. A degenerate hash makes one chain length (or one probe cluster of ), so operations are regardless of . The fix is a better hash function, not a resize.
EC5. Can exceed momentarily during normal operation?
Yes — you insert first (pushing above the threshold), then check and rehash. So right after the insert and before the resize, briefly; the resize restores it.
EC6. When should a table skip shrinking entirely, and what is a concrete default policy?
Define a minimum capacity (a common default is the table's initial size, e.g. 16) below which you never shrink. Rule: shrink to only if and ; otherwise stay put. This stops pointless churn on near-empty tables while still reclaiming memory on large ones.
EC7. During a rehash, is the table usable by other operations?
In a simple implementation, no — the rehash is a blocking pause. This is why latency-sensitive systems use incremental rehashing, spreading the moves across many operations.

Recall One-line self-test

Cover everything above. Can you state why doubling beats additive growth, why open addressing resizes earlier than chaining, and why you can't copy buckets by index? If yes on all three with reasons, you own this topic.

Answer these aloud
The three ideas are: geometric vs arithmetic series ( vs ), the cliff vs the line, and index changing when changes.