Collision Handling Using Chaining in DSA Python - Time & Space Complexity
When we use chaining to handle collisions in a hash table, we want to know how fast operations like search, insert, and delete run.
We ask: How does the time to do these operations grow as the number of items increases?
Analyze the time complexity of the following code snippet.
class HashTable:
def __init__(self, size):
self.size = size
self.table = [[] for _ in range(size)]
def insert(self, key, value):
index = hash(key) % self.size
self.table[index].append((key, value))
def search(self, key):
index = hash(key) % self.size
for k, v in self.table[index]:
if k == key:
return v
return None
This code shows a hash table using chaining where each bucket holds a list of key-value pairs.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Looping through the linked list (chain) at a bucket during search or insert.
- How many times: Depends on the number of items in that bucket, which grows with collisions.
As more items are added, chains get longer if the table size stays the same.
| Input Size (n) | Approx. Operations (search in chain) |
|---|---|
| 10 | About 1 (if table size ~10, chains short) |
| 100 | About 10 (chains longer if table size unchanged) |
| 1000 | About 100 (chains much longer without resizing) |
Pattern observation: If the table size stays fixed, operations grow roughly proportional to the number of items per bucket.
Time Complexity: O(1 + n/k)
This means the time depends on the average chain length, which is total items divided by table size.
[X] Wrong: "Hash table operations are always O(1) no matter what."
[OK] Correct: If many items collide into the same bucket, the chain grows and operations slow down, making time depend on chain length.
Understanding how chaining affects time helps you explain hash table performance clearly and shows you know how to handle collisions well.
"What if we resize the hash table when chains get too long? How would that change the time complexity?"
Practice
collision handling using chaining in hash tables?Solution
Step 1: Understand collision in hash tables
When two keys hash to the same index, a collision occurs.Step 2: How chaining handles collisions
Chaining stores all collided elements in a linked list at that index, allowing multiple elements to share the same slot.Final Answer:
Store collided elements in a linked list at the same index -> Option AQuick Check:
Chaining = linked list at index [OK]
- Thinking collisions replace existing elements
- Assuming collisions are ignored
- Believing resizing happens immediately on collision
Solution
Step 1: Understand chaining initialization
Chaining requires each slot to hold a list to store multiple elements.Step 2: Choose correct initialization
Using list comprehension to create a list of empty lists ensures each slot can hold multiple elements.Final Answer:
hash_table = [[] for _ in range(size)] -> Option DQuick Check:
Empty lists per slot = hash_table = [[] for _ in range(size)] [OK]
- Using [None] * size creates references to same list
- Using zeros instead of lists for chaining
- Using dict() which is not a list-based hash table
hash_table = [[] for _ in range(3)]
keys = [5, 8, 11]
for key in keys:
index = key % 3
hash_table[index].append(key)
print(hash_table)What is the output?
Solution
Step 1: Calculate indices for each key
5 % 3 = 2, 8 % 3 = 2, 11 % 3 = 2. All keys map to index 2.Step 2: Append keys to corresponding lists
All keys 5, 8, 11 are appended to hash_table[2], so hash_table = [[], [], [5, 8, 11]].Final Answer:
[[], [], [5, 8, 11]] -> Option BQuick Check:
Keys mod 3 = 2, all in last list [OK]
- Miscomputing modulo operation
- Appending keys to wrong index
- Confusing list positions in output
hash_table = [[]] * 4 key = 10 index = key % 4 hash_table[index].append(key) print(hash_table)
Solution
Step 1: Understand list multiplication behavior
Using [[]] * 4 creates 4 references to the same inner list, not 4 separate lists.Step 2: Effect on append operation
Appending to one index appends to all because all slots point to the same list.Final Answer:
Using [[]] * 4 creates references to the same list -> Option CQuick Check:
List multiplication duplicates references [OK]
- Assuming [[]] * 4 creates independent lists
- Incorrect modulo calculation
- Misunderstanding append method usage
Solution
Step 1: Calculate index for each key using modulo 5
7 % 5 = 2, 12 % 5 = 2, 17 % 5 = 2, 22 % 5 = 2, 27 % 5 = 2. All keys map to index 2.Step 2: Insert keys at index 2
All keys are appended to the list at index 2, so hash_table = [[], [], [7, 12, 17, 22, 27], [], []].Final Answer:
[[], [], [7, 12, 17, 22, 27], [], []] -> Option AQuick Check:
All keys mod 5 = 2, stored at index 2 [OK]
- Miscomputing modulo results
- Placing keys in wrong index
- Confusing list positions in output
Ready to prove it?
Pass the test and this pattern moves unknown
