Implement a hash map from scratch
An array of buckets, each a small list of (key, value) pairs. The key's hash picks the bucket; collisions append to that bucket's list and lookups compare keys along it. Grow and rehash once the average bucket stops being short — that is what keeps operations O(1).
Overview
Chaining versus open addressing
Separate chaining puts colliding entries in a list per bucket. Simple, deletion is trivial, and it tolerates a high load factor. This is what to implement under time pressure.
Open addressing stores everything in the array itself and probes for the next free slot on a collision. Better cache behaviour and less pointer chasing — it is what CPython actually uses — but deletion is genuinely hard.
Step through it
What to watch
- A collision is normal, not an error — both entries share a bucket.
- Lookups compare keys, never just hashes.
- A resize invalidates every bucket index at once.
Say this out loud
"Array of buckets with separate chaining. hash(key) % size picks the bucket, and I compare keys within it because collisions are expected. Resize when the load factor passes about 0.75, rehashing everything - the index depends on the size, so it all moves."