Problem Description
Design a HashSet without using any built-in hash table libraries. You need to implement a class MyHashSet that supports the following operations:
- add(key): Inserts the value key into the HashSet.
- contains(key): Returns whether the value key exists in the HashSet or not.
- remove(key): Removes the key from the HashSet, if present.
Key Insights
- We can simulate a hash table by using an array of buckets.
- Use a hash function (e.g., key mod bucket_size) to map each key to an index.
- Each bucket can be implemented as a list (or linked list) to handle collisions via chaining.
- Since key values are within [0, 10^6] and the number of operations is limited (10^4 calls), a reasonable bucket size (e.g., 1000) provides a good balance.
Space and Time Complexity
Time Complexity:
- add(key): O(N/buckets) on average, which is approximately O(1)
- remove(key): O(N/buckets) on average, approximately O(1)
- contains(key): O(N/buckets) on average, approximately O(1)
Space Complexity:
- O(buckets + number of keys), where buckets is a fixed-size array and keys are stored in lists.
Solution
We implement a HashSet using an array of buckets where each bucket is a list to handle collisions. A simple hash function (modulo operation) determines the bucket index for each key. When adding, checking, or removing a key, we compute its bucket index and then perform the operation in the corresponding list. This approach avoids built-in hash table libraries and handles potential collisions with chaining.