Design a Randomized Multiset
Company: LinkedIn
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: medium
Interview Round: Technical Screen
Quick Answer: This question evaluates the ability to design and implement a randomized multiset that correctly handles duplicate integer occurrences while providing expected O(1) insert, remove, and uniform getRandom operations, testing knowledge of data structures, randomness, and performance constraints.
Constraints
- 0 <= len(operations) <= 2 * 10^5
- len(operations) == len(values)
- Each `operations[i]` is one of `insert`, `remove`, or `getRandom`
- For `insert` and `remove`, `values[i]` is an integer in the range [-10^9, 10^9]
- For `getRandom`, `values[i]` is `None`
- 0 <= seed < 2^31
Examples
Input: (["insert", "insert", "insert", "getRandom", "remove", "getRandom"], [1, 1, 2, None, 1, None], 1)
Expected Output: [True, False, True, 1, True, 2]
Explanation: After the three inserts, `data = [1, 1, 2]`. The first generator state picks index 0, so `getRandom()` returns 1. `remove(1)` deletes the tracked occurrence at index 1 and swaps 2 into that slot, leaving `data = [1, 2]`. The next generator state picks index 1, so the final `getRandom()` returns 2.
Input: (["getRandom", "remove", "insert", "getRandom", "remove", "getRandom"], [None, 5, -3, None, -3, None], 0)
Expected Output: [None, False, True, -3, True, None]
Explanation: The multiset starts empty, so the first `getRandom()` returns `None`. Removing 5 fails. After inserting -3, the next `getRandom()` must return -3 because it is the only stored value. Removing -3 empties the multiset again.
Input: (["insert", "insert", "insert", "insert", "insert", "remove", "remove", "remove", "getRandom"], [1, 9, 1, 8, 1, 9, 8, 1, None], 5)
Expected Output: [True, True, False, True, False, True, True, True, 1]
Explanation: After removing 9, the last 1 is moved into its slot, so the tracked index list for value 1 becomes unsorted. Removing 8 leaves three 1s. The next `remove(1)` is the tricky case where the removed slot is filled by another 1 that was already the last array element. The final multiset is `[1, 1]`, so `getRandom()` returns 1.
Input: (["insert", "insert", "insert", "remove", "insert", "getRandom", "remove", "getRandom"], [10, 20, 30, 20, 20, None, 10, None], 1)
Expected Output: [True, True, True, True, True, 10, True, 30]
Explanation: Removing 20 swaps 30 into its old slot, then inserting 20 again gives `data = [10, 30, 20]`. With seed 1, the first `getRandom()` picks index 0 and returns 10. Removing 10 swaps 20 to the front, leaving `data = [20, 30]`. The next generator state picks index 1, so the final `getRandom()` returns 30.
Input: ([], [], 42)
Expected Output: []
Explanation: No operations means there are no results to return.
Hints
- A plain set is not enough because duplicates matter. Think about storing every occurrence in an array so `getRandom` can choose by index.
- To remove in O(1), swap the last array element into the deleted slot. An extra mapping from array index to its position inside that value's index list lets you update the moved element in O(1).