Problem Description
Implement a data structure that supports inserting elements (including duplicates), removing a single occurrence of an element, and getting a random element. Each operation should work on average in O(1) time, and the probability of returning an element should be linearly proportional to its frequency in the structure.
Key Insights
- Maintain an array (or list) to store the elements to allow for O(1) random access.
- Use a hash table that maps each value to a set (or list) of indices where the value is stored in the array.
- When removing an element, swap it with the last element in the array and update the hash map accordingly to maintain O(1) deletion.
- Handle duplicates by managing a collection of indices for each value.
Space and Time Complexity
Time Complexity: O(1) average for insert, remove, and getRandom.
Space Complexity: O(n) where n is the number of elements stored.
Solution
We use a dynamic array to store the numbers, which allows us to efficiently pick a random element using a random index. To support O(1) removals even for duplicates, we use a hash table where each key is a number and the value is a set (or similar container) of indices in the array where that number appears.
For insertion, we add the new value at the end of the array and record its index in the hash table.
For removal, we locate any index from the hash table corresponding to the value, swap the element at that index with the last element in the array, update indices in the hash table for the swapped element, and finally remove the last element from the array.
The getRandom operation simply picks a random index from the array and returns the element.