Randomized String Multiset With Average O(1) Insert, Remove and Weighted Random Pick
LinkedInSoftware Engineer · Technical ScreenLast updated
Design a collection of strings that allows duplicates and supports insert, remove and a random pick in average constant time, where each stored occurrence is equally likely to be returned. It tests hash map and array layout, index bookkeeping on removal, and how string keys change the cost analysis.
Design a data structure that holds a collection of strings in which the same string may be stored several times, and that supports the following operations in average O(1) time each:
class RandomizedStringBag:
def insert(self, val: str) -> bool: ...
def remove(self, val: str) -> bool: ...
def get_random(self) -> str: ...
insert(val)adds one occurrence ofval, even ifvalis already present. It returnsTrueifvalwas not present before the call, andFalseotherwise.remove(val)removes one occurrence ofvalif there is one. It returnsTrueif an occurrence was removed, andFalseifvalwas not present.get_random()returns one stored element at random, with every stored occurrence equally likely: a string stored k times among n stored occurrences in total is returned with probability k / n.
The interviewer presented this as the familiar integer version of the problem with one difference: the elements are strings instead of numbers.
Clarifying Questions
- What should
get_randomdo when the collection is empty? - Does O(1) treat hashing and comparing a string as constant time, or should the analysis account for string length?
- Can strings be long, and are heavy duplicates expected, so that memory per occurrence matters?
- Will the structure be used from several threads at once?
Hints
Hint 1
Picking at random: Think about which layout makes choosing a uniformly random occurrence a single step, and what deleting from the middle of that layout would cost.
Hint 2
Finding an occurrence fast: To delete one occurrence of a value in constant time, you must already know where some occurrence of it is. Decide what to remember per distinct string, and what has to change when an element moves.
Follow-up questions
- Change `get_random` so that every distinct string is equally likely, regardless of how many times it is stored.
- Add `remove_all(val)`, which removes every occurrence of `val`. What does it cost?
- The strings are long and heavily duplicated. How do you avoid storing a copy per occurrence?
- Make the structure safe to use from several threads.
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.