When to use a hash table
Use a hash table (a hash map or a hash set) when you need:
- Lookup by key in about one step: "the user with this ID", "the price of this product".
- To count things: how many times each word, error or visitor appears (frequency counting).
- To answer "have I seen this before?": removing duplicates, spotting a repeat, checking membership.
- To group items by a key, such as orders by customer.
- A cache or memo: remember an answer so you never compute it twice.
- To make a slow nested loop into one pass: "for each item, is its partner already stored?"
Use something else when:
- You need keys in sorted order, or range queries such as "all scores from 1,000 to 2,000": use a balanced tree.
- You need a guaranteed worst case on untrusted input: a balanced tree gives O(log n) always.
- Keys are small whole numbers in a known range: a plain array indexed by the key is simpler and faster.
- You need items in insertion order: use an ordered map (Java
LinkedHashMap, and Python'sdictalready keeps insertion order).
Do not build a hash table by hand. Every language has one (see the real-world section). Writing one is for learning and interviews.
How a hash table works
A hash table stores key and value pairs and finds a pair by its key without searching through the others.
A hash function turns a key into a number, and that number (modulo the number of buckets) says which bucket holds the key. The same key always gives the same bucket.
The steps for put("cat", 5):
- Run the hash function on
"cat"to get a number. - Take that number modulo the number of buckets to get a bucket index.
- Go straight to that bucket and store the pair there.
Looking up "cat" repeats steps 1 and 2 and reads the bucket. No scan through other keys is needed, which is why it is O(1) on average.
Two things can go wrong, and tables handle both:
- Collisions. Two different keys can land in the same bucket. The two main fixes are chaining (each bucket holds a small list, as in the demo below) and open addressing (if the bucket is taken, probe for the next free one).
- Crowding. The load factor is items divided by buckets. When it passes a limit, the table allocates more buckets, usually double, and puts every key back using the new size. This is called rehashing.
A hash set is a hash table that stores only keys, with no values. It answers "is this in the set?"
Try it
Start with the animals. The demo uses a very simple hash: it adds up the character codes of the key. Real tables mix the bits far better, but the idea is the same.
Hash table
Step 1 of 1 · Press Space to play, arrow keys to step- 0cat
- 1bird
- 2dog
- 3empty
Start: a table with 4 buckets holding 3 keys. Use Put, Get or Delete above.
- items:
- 3
- buckets:
- 4
- load factor:
- 0.75
- key checks:
- 0
load factor = items / buckets. key checks = keys compared in this operation. The hash here just adds up character codes, so anagrams collide on purpose.
Things to try:
- Put
cat, then Putdog. Each lands in its own bucket, and Getcattakes one key check. - Pick Colliding words and Put
cat.actandcathave the same letters, so the same hash, so they share a bucket. Getcatnow needs 2 key checks. - Keep putting keys such as
a,b,cand watch the load factor. When it passes 0.75 the buckets double and every key is re-placed.
Hash table operations: put, get and delete
Put. Hash the key, pick the bucket, and add the pair. If the key is already there, replace its value instead. If the load factor is now too high, grow and rehash.
Get. Hash the key, pick the bucket, and compare the key with each item in the bucket until one matches. With short chains that is one or two comparisons.
Delete. Find the pair the same way and remove it. In open addressing, tables mark the slot as deleted instead of emptying it, so later probes do not stop too early.
Frequency counting. Use the item as the key and a number as the value. For each item, add one to its count. One pass over n items costs O(n).
Interview fact. A hash table gives O(1) on average, but O(n) in the worst case, when every key collides. It also keeps no useful order, so "smallest key" or "all keys between a and b" is not something it does well.
Hash table time complexity
| Operation | Average | Worst case |
|---|---|---|
| Put (insert or update) | O(1) | O(n) |
| Get (lookup) | O(1) | O(n) |
| Delete | O(1) | O(n) |
| Resize and rehash | O(n), rare | O(n) |
| Walk every key | O(n) | O(n) |
| Memory | O(n) | O(n) |
The worst case happens when many keys end up in the same bucket, for example with a poor hash function. Good hash functions, and resizing to keep the load factor low, make it very unlikely.
Hash tables vs other data structures
The right choice depends on what you do most. n is the number of items and k is the number of results returned.
| What you need | Hash map | Balanced tree | Unsorted array | Sorted array |
|---|---|---|---|---|
| Find by key | O(1) average | O(log n) | O(n) | O(log n) |
| Insert | O(1) average | O(log n) | O(1) at the end | O(n) |
| Delete by key | O(1) average | O(log n) | O(n) | O(n) |
| Walk keys in sorted order | O(n log n), sort first | O(n) | O(n log n), sort first | O(n) |
| Range query ("between a and b") | O(n) | O(log n + k) | O(n) | O(log n + k) |
| Nearest key | O(n) | O(log n) | O(n) | O(log n) |
| Guaranteed worst case | No, O(n) | Yes, O(log n) | n/a | Yes for lookup |
The bold cells show where each one wins. A hash table is the fastest for exact-key work and the weakest for anything that depends on order.
How to explain hash tables in an interview
- Say how it works in one breath: "hash the key to a bucket index, go straight there."
- Give both costs: "O(1) on average, O(n) worst case if everything collides."
- Name how collisions are handled: "chaining or open addressing", and what the load factor is.
- Say it has no order, and name the tree as the alternative when you need order.
- For counting or "seen before" problems, say you will trade O(n) memory for O(n) time.