705. Design HashSet
🟩 Easy
Design a HashSet without using any built-in hash table libraries.
Implement MyHashSet
class:
void add(key)
Inserts the valuekey
into the HashSet.bool contains(key)
Returns whether the valuekey
exists in the HashSet or not.void remove(key)
Removes the valuekey
in the HashSet. Ifkey
does not exist in the HashSet, do nothing.
Example 1
Input: ["MyHashSet", "add", "add", "contains", "contains", "add", "contains", "remove", "contains"] [[], [1], [2], [1], [3], [2], [2], [2], [2]] Output: [null, null, null, true, false, null, true, null, false] Explanation: MyHashSet myHashSet = new MyHashSet(); myHashSet.add(1); // set = [1] myHashSet.add(2); // set = [1, 2] myHashSet.contains(1); // return True myHashSet.contains(3); // return False, (not found) myHashSet.add(2); // set = [1, 2] myHashSet.contains(2); // return True myHashSet.remove(2); // set = [1] myHashSet.contains(2); // return False, (already removed)
Constraints
0 <= key <= 10^6
At most
10^4
calls will be made toadd
,remove
, andcontains
.
Solution
My Solution (Chaining with Linked Lists)
Optimal Solution 1 (Open Addressing with Linear Probing)
Optimal Solution 2 (Bit Vector for Small Keys)
Approach Analysis
This problem showcases different hash set implementation strategies:
Chaining with Linked Lists (Your Solution):
Separate chaining for collisions
Dynamic resizing
Linked list traversal
Good for high load factors
Open Addressing:
Linear probing
In-place collision resolution
Efficient cache usage
Better for low load factors
Bit Vector:
Direct mapping
Bit-level operations
No collisions
Perfect for integers
Visualization of Approaches
Chaining Process (Your Solution)
Open Addressing Process
Bit Vector Process
Complexity Analysis
Chaining Solution (Your Solution)
Time:
Add: O(1) average, O(n) worst
Remove: O(1) average, O(n) worst
Contains: O(1) average, O(n) worst
Space: O(n)
Linked list nodes
Dynamic resizing
Load factor control
Open Addressing Solution
Time:
Add: O(1) average, O(n) worst
Remove: O(1) average, O(n) worst
Contains: O(1) average, O(n) worst
Space: O(n)
Contiguous array
Better cache locality
Load factor < 0.75
Bit Vector Solution
Time:
Add: O(1)
Remove: O(1)
Contains: O(1)
Space: O(M)
M = max key value
Very space efficient
Fixed size array
Why Solutions Work
Chaining Logic:
Distributes collisions
Maintains insertion order
Easy to implement
Flexible growth
Open Addressing:
Cache-friendly
No extra pointers
Simple probing
Good locality
Bit Vector:
Direct mapping
Bit-level operations
No collisions
Perfect for integers
When to Use
Chaining When:
High load factor
Memory not critical
Order matters
Many collisions
Open Addressing When:
Cache performance critical
Memory contiguous
Low load factor
Few collisions
Bit Vector When:
Small key range
Memory critical
Integer keys only
Fast operations needed
Common Patterns & Applications
Related Problems:
Design HashMap
LRU Cache
Insert Delete GetRandom O(1)
Find Duplicate
Key Techniques:
Hash functions
Collision handling
Dynamic resizing
Memory management
Interview Tips
Solution Highlights:
Collision handling
Load factor management
Space efficiency
Time complexity
Common Pitfalls:
Poor hash function
Missing edge cases
Memory leaks
Infinite loops
Testing Strategy:
Empty set
Duplicate keys
Collisions
Deletions
Resizing
Follow-up Questions:
Thread safety?
Custom objects?
Persistence?
Distribution?
Last updated
Was this helpful?