Insert Delete GetRandom O(1)
Keep two structures in sync. vals holds every value packed with no gaps, so getRandom is vals[rand() % size]. pos maps each value to its index in vals, so we can find any value in O(1). To remove val at index i, move the last value into slot i, update that moved value's index in pos, and pop_back. Nothing shifts.
The two structures always agree: for every stored value v, vals[pos[v]] == v, and vals has no gaps. Every operation must leave this true.
Problem
Build a class RandomizedSet that stores a set of distinct integers and supports three operations, each in O(1) average time:
bool insert(int val): addvalif it is not already there. Returntrueif it was added,falseif it was already present.bool remove(int val): deletevalif it is there. Returntrueif it was removed,falseif it was not present.int getRandom(): return one of the stored values, chosen at random. Every stored value must have the same chance of being returned.
A sequence of calls on one RandomizedSet object: insert(val), remove(val) and getRandom().
The return value of each call: true/false for insert and remove, and a stored value for getRandom.
1 is added. 2 is not there, so remove(2) fails. 2 is added, so the set is {1, 2} and getRandom returns 1 or 2 with equal chance. 1 is removed. 2 is already there, so insert(2) fails. Now the set is {2}, so getRandom must return 2.
- β’ β2^31 β€ val β€ 2^31 β 1
- β’ At most 2 Β· 10^5 calls in total
- β’ getRandom is only called when the set has at least one value
First, think yourself
Before opening any solution, try to answer these on paper. Use hints only when stuck β each hint is counted.
- 1.
Which container gives me a random element in O(1)? Which one tells me "is x here?" in O(1)? Are they the same container?
- 2.
If I keep the values in a vector, what exactly is slow about removing one from the middle?
- 3.
Does the order of the values in the set matter at all?
- 4.
If order does not matter, is there a cheap way to delete from a vector without shifting anything?
- 5.
If I move a value to a new index, what else must I update so I can still find it later?
Brute force approach
Optimized approach
Why does this algorithm work?
Dry run
All approaches compared
| Approach | Idea | Time | Space |
|---|---|---|---|
| Brute Force | Keep values in a vector; insert and remove search it linearly | O(N) | O(N) |
| Optimal | Vector for random access, map for O(1) lookup; delete by swapping with the last value | O(1) | O(N) |
Why does this belong to this pattern?
- βeach operation in O(1)βNo scanning allowed. Every operation needs a direct lookup β hash map.
- βrandom element, equal chanceβNeeds index-based access with no gaps β a packed vector.
- βset (order does not matter)βWe may rearrange the vector freely β delete by swapping with the last element.
This is the anchor of the design sub-pattern: no single container is fast at everything, so we pair a hash map with a second structure and keep them in sync. Here the second structure is a vector, and the trick that keeps it packed is "swap with last, then pop". LRU Cache uses the same idea with a linked list instead, because there the order matters.
Don't make this mistake
After the swap, last lives at index i, but the map still says it is at the old last index, which no longer exists. The next remove(last) will read the wrong slot and corrupt the set.
When val is itself the last value, last == val. Erasing first and then writing pos[last] = i puts val back into the map, even though it was removed. Later insert(val) returns false by mistake. Updating first and erasing last is correct in both cases.
This shifts every later element, so remove becomes O(N), and every shifted value's index in the map is now wrong too. Swap with the last element instead; a set's order does not matter.
Pattern-confusion trap. A hash set is the obvious tool for "insert / remove / contains", but it has no index. Reaching the k-th element means walking the iterator, which is O(N). The design pattern here is a map plus an array, so that random access by index is possible.
Want to implement this?
Write it yourself on LeetCode, then come back and compare your code with the solutions above.
Open coding workspaceHow this concept connects to System Design & C++ Systems
Top engineering interviews test whether you understand how algorithms like Arrays & Hashing translate into production architectures and low-level memory mechanics.