
Problem Statement
The RandomizedSet
class is a data structure designed to handle a collection of unique integer elements with the ability to perform three primary operations: inserting an integer, removing an integer, and retrieving a random integer. Each of these operations should ideally run in constant average time complexity (O(1)).
- The method
RandomizedSet()
is used to initialize theRandomizedSet
object. - The method
insert(int val)
adds an integerval
to the set if it is not already present. The return value istrue
ifval
was not previously present in the set, andfalse
otherwise. - The method
remove(int val)
removes an integerval
from the set if it exists, returningtrue
if the integer was present andfalse
if it was not. - Finally, the
getRandom()
method returns a random integer from the current elements in the set. Every element should have the same likelihood of being selected, and this selection is guaranteed to be possible only when there is at least one element in the set.
Examples
Example 1
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.
Constraints
-2³¹ <= val <= 2³¹ - 1
- At most
2 * 10⁵
calls will be made toinsert
,remove
, andgetRandom
. - There will be at least one element in the data structure when
getRandom
is called.
Approach and Intuition
Insert Operation (insert(int val)
)
To insert a unique integer in average O(1) time:
- Use a combination of a hash table and a list (array).
- Append the new value to the array and store its index in the hash table.
- Appending and updating the hash table both take constant time.
Remove Operation (remove(int val)
)
To maintain constant time during removal:
- Use the hash table to find the index of the value.
- Swap the value with the last element in the array.
- Update the hash table and remove the last element.
- This avoids shifting elements, preserving O(1) performance.
getRandom()
Operation
To select a random element:
- Since all values are stored in an array, choose a random index.
- This ensures uniform probability and constant time selection.
Example Demonstration
randomizedSet.insert(1)
→ Returnstrue
, inserts1
.randomizedSet.remove(2)
→ Returnsfalse
,2
not present.randomizedSet.insert(2)
→ Returnstrue
, adds2
.randomizedSet.getRandom()
→ Returns1
or2
.randomizedSet.remove(1)
→ Removes1
, returnstrue
.randomizedSet.insert(2)
→2
is already present, returnsfalse
.randomizedSet.getRandom()
→ Only2
is present, so returns2
.
The methods provide a concise and efficient solution to dynamically manage a set of unique integers with optimal time complexity.
Solutions
- Java
class UniqueSet {
Map<Integer, Integer> valueMap;
List<Integer> values;
Random random = new Random();
/** Initializes the data structure. */
public UniqueSet() {
valueMap = new HashMap<>();
values = new ArrayList<>();
}
/** Adds a value. Returns true if it was not present. */
public boolean insert(int val) {
if (valueMap.containsKey(val)) return false;
valueMap.put(val, values.size());
values.add(values.size(), val);
return true;
}
/** Removes a value. Returns true if it was present. */
public boolean remove(int val) {
if (!valueMap.containsKey(val)) return false;
// Swap with last item and update the hashmap
int lastValue = values.get(values.size() - 1);
int removeIndex = valueMap.get(val);
values.set(removeIndex, lastValue);
valueMap.put(lastValue, removeIndex);
// Remove the last item
values.remove(values.size() - 1);
valueMap.remove(val);
return true;
}
/** Returns a random element. */
public int getRandom() {
return values.get(random.nextInt(values.size()));
}
}
The given Java code implements a data structure named UniqueSet
that allows for efficient insertion, deletion, and access to random elements, all in constant time O(1). Below is an overview of how each operation is handled:
Initialization:
valueMap
, a HashMap, is used to store values and their indexes.values
, an ArrayList, is used to keep the elements.
Insert Operation (
insert
method):- Checks if the value is already in
valueMap
. - If not present, adds the value to
values
and stores its index invalueMap
. - Returns
true
if the value was added, otherwisefalse
.
- Checks if the value is already in
Delete Operation (
remove
method):- Checks if the value exists in
valueMap
. - If present, gets the index and swaps the last element with the element to be removed in the
values
list for efficient removal. - Updates the
valueMap
with the new index of the swapped last element. - Removes the last element from
values
and the original value fromvalueMap
, ensuring the operation remains constant time. - Returns
true
if the value was removed, otherwisefalse
.
- Checks if the value exists in
Get Random Operation (
getRandom
method):- Generates a random index and retrieves the value from
values
at that index.
- Generates a random index and retrieves the value from
This structure is particularly useful in scenarios where average time complexity matters and operations need to be as efficient as possible on average-case terms. As a result, the combination of a hashmap and an array list ensures that each operation—insertion, deletion, and access—is performed in O(1) time, with the randomness efficiently managed by Java's Random
class.
No comments yet.