AlgoMaster Logo

Insert Delete GetRandom O(1)

Last Updated: April 4, 2026

medium
4 min read

Understanding the Problem

We need to design a data structure that supports three operations, all in average O(1) time: inserting an element, removing an element, and returning a uniformly random element.

The tricky part is that no single standard data structure handles all three well. A hash set gives O(1) insert and remove, but there's no way to pick a random element in O(1) because you can't index into a hash set. An array gives O(1) random access (just pick a random index), but removing an arbitrary element is O(n) because you'd need to shift everything.

The key observation is that we can combine both: use an array for O(1) random access and a hash map for O(1) lookups. The clever trick that makes removal O(1) is swapping the element to delete with the last element in the array, then popping the last element.

Key Constraints:

  • At most 2 * 10^5 calls → Each operation must be O(1) on average. Linear scans per call would give O(n) per call and TLE with this many operations.
  • -2^31 <= val <= 2^31 - 1 → Values span the full integer range, so we can't use a fixed-size boolean array. We need a hash map for membership checks.
  • At least one element when getRandom is called → No need to handle the empty-set case for getRandom.

Approach 1: Hash Set with Linear Scan for Random

Intuition

The most straightforward approach is to use a hash set for O(1) insert and remove, then convert it to a list whenever we need a random element. A hash set handles membership checks, insertion, and deletion in O(1). For getRandom, we can copy all elements into a list and pick a random index.

This works correctly, but converting the entire set to a list on every getRandom call is O(n), which violates the O(1) requirement. It's a useful starting point, though, because it makes the bottleneck obvious.

Algorithm

  1. Maintain a hash set to store all current elements.
  2. For insert(val): check if val is in the set. If not, add it and return true. Otherwise return false.
  3. For remove(val): check if val is in the set. If so, remove it and return true. Otherwise return false.
  4. For getRandom(): convert the set to a list (or array), generate a random index, and return the element at that index.

Example Walkthrough

Input:

0
RandomizedSet
1
insert
2
remove
3
insert
4
getRandom
5
remove
6
insert
7
getRandom
operations

For each operation, we simply add/remove from a hash set. When getRandom is called, we convert the set to an array and pick a random index. With set = {1, 2}, getRandom converts to [1, 2] and picks randomly:

0
-
1
true
2
false
3
true
4
2
5
true
6
false
7
2
result

Code

The bottleneck is getRandom: we rebuild the entire array from scratch every time. What if we maintained an array alongside the hash map so random access by index is always available in O(1)?

Approach 2: Array + Hash Map (Optimal)

Intuition

The insight is to use two data structures together, each covering the other's weakness. An array gives us O(1) random access: just generate a random index and return the element there. A hash map gives us O(1) lookups: given a value, we can instantly find where it sits in the array.

Insert is straightforward: append the new element to the end of the array and record its index in the hash map. getRandom is also easy: pick a random index from 0 to size-1 and return the array element there.

The clever part is removal. Removing from the middle of an array is normally O(n) because you need to shift elements. But here's the trick: we don't care about the order of elements. So instead of shifting, we swap the element we want to remove with the last element in the array, update the hash map for the swapped element's new position, and then pop the last element. Both the swap and the pop are O(1).

Algorithm

  1. Maintain an array list that stores all current elements, and a hash map valToIndex that maps each value to its index in the array.
  2. For insert(val): if val is already in the map, return false. Otherwise, append val to the end of the array, record its index in the map, and return true.
  3. For remove(val): if val is not in the map, return false. Otherwise, get val's index from the map. Swap the element at that index with the last element in the array. Update the map for the swapped element's new index. Remove the last element from the array and remove val from the map. Return true.
  4. For getRandom(): generate a random index between 0 and size-1 (inclusive) and return the array element at that index.

Example Walkthrough

1Initial state: list is empty, map is empty
1/9
1Initial state: map is empty
1/9

Code