Hello, reader ๐๐ฝ ! Welcome to day 59 of the series on Problem Solving. Through this series, I aim to pick up at least one question everyday and share my approach for solving it.
Today, I will be picking up LeetCode's daily challenge problem: 380. Insert Delete GetRandom O(1).
๐ค Problem Statement
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.
The functions need to be implemented such that each works in average O(1) time complexity.
- E.g.:
["RandomizedSet", "insert", "remove", "insert", "getRandom", "remove", "insert", "getRandom"]
[[], [1], [2], [2], [], [1], [2], []]
[null, true, false, true, 2, true, false, 2]
๐ฌ Thought Process - Hash Map + Array
- We have to focus on three functions:
insert()
remove()
getRandom()
- Let's first focus on
insert()
andremove()
. We know that for array insertion and removal could beO(n)
in the worst case. Hence we cannot use an array to store all the integers. - Stack or Queue could work, but then they only support only removals from front or back.
The two data structures that would help us in getting an
O(1)
operations are: set and map.Let's think about
getRandom()
. This function could have been easy if we had an array. Then we could have generated a random index whose range would be within the size of the array. Since random access isO(1)
in an array, this works.- But the problem is we cannot use an array for insertion and removal. So what can we do?
- In the worst case, removal from an array does cause
O(n)
. But the removal (and insertion) of an element from the end of an array is only anO(1)
operation. - So we can try to make use of this. But there's no guarantee that every time the value that needs to be removed is in the end of the array.
- The way around this is that whenever we have to remove a value
val
, we can swap it with last element in the array. - But then for that we should know in which index the value
val
is stored in. Hence, we need a quick way of accessing the indices in the array where every value is stored. - So the idea behind this problem's approach boils down to this:
- Use a map to store
<value, index>
pairs and an array to store all the values - Insert an element
val
to the array at index i and save theval, i
pair in the map - Remove an element
val
at index i by swapping it with the last elementlast
in the array at index j. Remove theval, i
value and update the pairlast, j
tolast, i
in the map. - Generate a random index
random
whose range is between[0, array size]
and return the value of the array inrandom
.
- Use a map to store
๐ฉ๐ฝโ๐ป Solution - Hash Map + Array
Below is the code for the approach using hash map and array. ``` class RandomizedSet { Map values; List valueIndices; public RandomizedSet() {
values = new HashMap(); valueIndices = new ArrayList();
}
public boolean insert(int val) {
if(values.containsKey(val)) return false; // insert the current value in the last index int index = values.size(); values.put(val, index); // insert the current value in the last index valueIndices.add(index, val); return true;
}
public boolean remove(int val) {
if(!values.containsKey(val)) return false; // Get the index of current val int valIndex = values.get(val); // Get the last index and the last val int lastIndex = valueIndices.size() - 1; int lastVal = valueIndices.get(lastIndex); // removes curr element from map values.remove(val); // removes curr element from index valueIndices.remove(valIndex); if(val == lastVal) { return true; } // add the last value to valIndex in the list valueIndices.add(valIndex, lastVal); // set the lastVal index as valIndex values.put(lastVal, valIndex); // remove the last index from the list valueIndices.remove(lastIndex); return true;
}
public int getRandom() {
Random random = new Random(); int randomIndex = random.nextInt(valueIndices.size()); return valueIndices.get(randomIndex);
} }
/**
- Your RandomizedSet object will be instantiated and called as such:
- RandomizedSet obj = new RandomizedSet();
- boolean param_1 = obj.insert(val);
- boolean param_2 = obj.remove(val);
- int param_3 = obj.getRandom();
*/
Time Complexity:- insert: O(1)
- remove: O(1)
- getRandom: O(1) Space Complexity: O(n) ```
- You can find the link to the GitHub repo for this question here: 380. Insert Delete GetRandom O(1).
Conclusion
That's a wrap for today's problem. If you liked my explanation then please do drop a like/ comment. Also, please correct me if I've made any mistakes or if you want me to improve something!
Thank you for reading!