Implement the RandomizedSet
class:
RandomizedSet()
: Initializes the RandomizedSet
object.bool insert(int val)
: Inserts an item val
into the set if not present. Returns true
if the item was not present, false
otherwise.bool remove(int val)
: Removes an item val
from the set if present. Returns true
if the item was present, false
otherwise.int getRandom()
: Returns a random element from the current set of elements (it's guaranteed that at least one element exists when this method is called). Each element must have the same probability of being returned.You must implement the functions of the class such that each function works in average O(1)
time complexity.
Example:
Input
["RandomizedSet", "insert", "remove", "insert", "getRandom", "remove", "insert", "getRandom"]
[[], [1], [2], [2], [], [1], [2], []]
Output
[null, true, false, true, 2, true, false, 2]
Explanation
RandomizedSet randomizedSet = new RandomizedSet();
randomizedSet.insert(1); // Inserts 1 to the set. Returns true as 1 was inserted successfully.
randomizedSet.remove(2); // Returns false as 2 does not exist in the set.
randomizedSet.insert(2); // Inserts 2 to the set, returns true. Set now contains [1,2].
randomizedSet.getRandom(); // getRandom() should return either 1 or 2 randomly.
randomizedSet.remove(1); // Removes 1 from the set, returns true. Set now contains [2].
randomizedSet.insert(2); // 2 was already in the set, so return false.
randomizedSet.getRandom(); // Since 2 is the only number in the set, getRandom() will always return 2.
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The main idea is to keep track of all numbers in a straightforward manner. For each operation, we'll just do the most basic thing we can think of to achieve the desired outcome, without worrying about efficiency.
Here's how the algorithm would work step-by-step:
import random
class RandomizedSet:
def __init__(self):
self.number_list = []
def insert(self, value):
if value not in self.number_list:
self.number_list.append(value)
return True
return False
def remove(self, value):
if value in self.number_list:
self.number_list.remove(value)
return True
return False
def getRandom(self):
# Use python's random library
# to pick a random index.
random_index = random.randint(0, len(self.number_list) - 1)
# Return a random number from the list
# after selecting a random index
return self.number_list[random_index]
To make these operations super fast, we'll use a clever combination of two data structures. One will let us quickly look up if a number exists, and the other will let us easily pick a random number.
Here's how the algorithm would work step-by-step:
import random
class RandomizedSet:
def __init__(self):
self.array_of_numbers = []
self.position_map = {}
def insert(self, value):
if value in self.position_map:
return False
self.array_of_numbers.append(value)
self.position_map[value] = len(self.array_of_numbers) - 1
return True
def remove(self, value):
if value not in self.position_map:
return False
# Get the index of the element to remove.
index_to_remove = self.position_map[value]
# Get the last element in the array.
last_element = self.array_of_numbers[-1]
# Replace the element to remove with the last element.
self.array_of_numbers[index_to_remove] = last_element
# Update the position of the last element.
self.position_map[last_element] = index_to_remove
# Remove the last element from the array. Important for O(1) removal
self.array_of_numbers.pop()
# Remove the value from the position map.
del self.position_map[value]
#Update position_map if the array isn't empty
if last_element != value:
self.position_map[last_element] = index_to_remove
return True
def getRandom(self):
#Ensure we can return a random number
if not self.array_of_numbers:
return None
# Generate a random index within the bounds of the array.
random_index = random.randint(0, len(self.array_of_numbers) - 1)
return self.array_of_numbers[random_index]
Case | How to Handle |
---|---|
Inserting a value that already exists in the set. | The insert() method should return false without modifying the set. |
Deleting a value that does not exist in the set. | The delete() method should return false without modifying the set. |
Calling getRandom() on an empty set. | The getRandom() method should handle the edge case of empty set gracefully, likely returning null or throwing exception based on pre-defined behavior. |
Maximum number of inserts allowed (memory constraints). | The solution should consider memory constraints and potentially throw an exception if the set reaches its maximum capacity. |
Large integer values for inserted elements (potential integer overflow). | Use appropriate data types (e.g., long) to handle large integer values to prevent integer overflow. |
Repeated insertions and deletions of the same element. | Ensure the underlying data structures (list and hash map) remain consistent with each insert and delete to guarantee correctness. |
Random number generator failing or producing biased results. | Ensure the random number generator is properly initialized and unbiased for uniform element selection. |
Deleting the last element in the list. | Deleting the last element should update the index in the hashmap to correctly point to the new location and ensure proper functioning of getRandom(). |