Hash Table Concept and Hash Functions in DSA Python - Time & Space Complexity
We want to understand how fast a hash table can find or store data using hash functions.
The question is: how does the time to do these operations change as we add more items?
Analyze the time complexity of the following code snippet.
class SimpleHashTable:
def __init__(self, size):
self.size = size
self.table = [None] * size
def hash_function(self, key):
return hash(key) % self.size
def insert(self, key, value):
index = self.hash_function(key)
self.table[index] = value
def get(self, key):
index = self.hash_function(key)
return self.table[index]
This code creates a simple hash table with a basic hash function and supports insert and get operations.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Calculating the hash and accessing the array index.
- How many times: Each insert or get does this once, no loops inside these methods.
Each operation does a quick calculation and direct access, so time stays about the same even if the table grows.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 1 operation per insert/get |
| 100 | 1 operation per insert/get |
| 1000 | 1 operation per insert/get |
Pattern observation: The time does not increase with more items, it stays constant.
Time Complexity: O(1)
This means each insert or get takes about the same time no matter how many items are stored.
[X] Wrong: "Hash table operations always take longer as more items are added because the array gets bigger."
[OK] Correct: The hash function directly finds the spot, so time stays constant unless many items collide in the same spot.
Understanding hash tables and their time complexity shows you know how to store and find data quickly, a key skill in many coding problems.
"What if many keys hash to the same index and we handle collisions by searching a list? How would the time complexity change?"
Practice
Solution
Step 1: Understand the role of a hash function
A hash function takes a key and converts it into a number that can be used as an index in the hash table.Step 2: Compare with other options
Sorting keys, encrypting data, or counting elements are not the main roles of a hash function in a hash table.Final Answer:
To convert a key into an index for storing data -> Option CQuick Check:
Hash function = key to index [OK]
- Thinking hash function sorts keys
- Confusing hash function with encryption
- Assuming hash function counts elements
Solution
Step 1: Identify the correct modulus operation
The hash function should return the remainder when key is divided by 10, which is done using the modulus operator '%'.Step 2: Check syntax correctness
def hash_func(key): return key % 10 uses 'return key % 10' which is correct syntax and logic. Other options use division, multiplication, or addition which do not produce the remainder.Final Answer:
def hash_func(key): return key % 10 -> Option AQuick Check:
Use % for remainder in hash function [OK]
- Using division instead of modulus
- Multiplying or adding instead of modulus
- Incorrect function syntax
def simple_hash(key):
return key % 5
hash_table = [None] * 5
keys = [12, 22, 17]
for key in keys:
index = simple_hash(key)
hash_table[index] = key
print(hash_table)Solution
Step 1: Calculate hash indexes for each key
12 % 5 = 2, 22 % 5 = 2, 17 % 5 = 2. All three keys map to the same index 2.Step 2: Trace the assignments
The code assigns directly to hash_table[index] with no collision handling, so later keys overwrite earlier ones at index 2: 12 -> 22 -> 17. Final state: [None, None, 17, None, None].Final Answer:
[None, None, 17, None, None] -> Option BQuick Check:
All keys hash to index 2, last key stored [OK]
- Assuming keys store at different indexes without collision
- Ignoring overwriting in hash table
- Miscomputing modulus
def hash_func(key):
return key // 10
hash_table = [None] * 10
index = hash_func(25)
hash_table[index] = 25
print(hash_table)Solution
Step 1: Understand the hash function logic
The function uses integer division '//' which divides key by 10 and returns the quotient, not the remainder.Step 2: Check impact on indexing
For key=25, 25 // 10 = 2, which is a valid index but this is not a typical hash function behavior. Usually, modulus '%' is used to get remainder for index within table size.Step 3: Identify the error
Using '//' can cause indexes outside the hash table size if keys are large. Modulus '%' should be used to ensure index is within table size.Final Answer:
Using integer division instead of modulus causes wrong indexing -> Option DQuick Check:
Use % for index, not // [OK]
- Confusing integer division with modulus
- Ignoring table size limits
- Assuming code runs without error
Solution
Step 1: Understand the requirement
The hash function must return an integer index between 0 and 9 for any string input.Step 2: Analyze each option
def hash_func(s): return sum(ord(c) for c in s) % 10 sums ASCII values of all characters and uses modulus 10 to keep index in range 0-9. def hash_func(s): return len(s) * 10 multiplies length by 10, which can exceed 9. def hash_func(s): return ord(s[0]) returns ASCII of first char, which can be larger than 9. def hash_func(s): return s.count('a') counts 'a's, which can be any number, possibly larger than 9.Step 3: Choose correct function
Only def hash_func(s): return sum(ord(c) for c in s) % 10 guarantees index in 0-9 range for any string.Final Answer:
def hash_func(s): return sum(ord(c) for c in s) % 10 -> Option AQuick Check:
Sum ASCII % table size for string hash [OK]
- Using string length times 10 as index
- Using ASCII code directly without modulus
- Using character count without range check
Ready to prove it?
Pass the test and this pattern moves unknown
