InterviewPrepKit

Home / Coding / Arrays & Hashing

Insert Delete GetRandom O(1)

medium Original ↗
Solving tips
  • Recognize this as a container-pairing design problem: no single structure does O(1) insert, delete, and uniform random, so combine a dynamic array (for O(1) random index access) with a dict value->index (for O(1) membership/location).
  • Key trick for O(1) delete: never remove from the middle; overwrite the doomed slot with the last array element, fix that element's index in the dict, then pop the tail.
  • Target O(1) average per operation and O(n) space; getRandom is uniform because the array is always gap-free.
  • Common pitfall: when the removed value is itself the tail, order matters, but doing the swap then del by key stays correct; forgetting to update the moved element's index corrupts later removals.

Problem

Design a set-like data structure RandomizedSet supporting three operations, each in average O(1) time:

  • insert(val) — add val if absent; return True if it was added, False if it was already present.
  • remove(val) — delete val if present; return True if it was removed, False if it wasn’t there.
  • getRandom() — return a uniformly random element from the current set (each element equally likely). It is guaranteed the set is non-empty when this is called.

The challenge is that no single standard container gives you all three: a hash set has O(1) insert/remove but no O(1) uniform sampling; an array samples in O(1) but removes in O(n).

Examples

Example 1:

insert(1) -> True    # {1}
remove(2) -> False   # 2 not present
insert(2) -> True    # {1, 2}
getRandom() -> 1 or 2, each with probability 1/2
remove(1) -> True    # {2}
insert(2) -> False   # already there
getRandom() -> 2     # only element left

Example 2: insert(5) -> True, insert(5) -> False — a duplicate insert reports failure and the set still holds one 5.

Constraints

  • -2^31 <= val <= 2^31 - 1
  • Up to 2 * 10^5 total calls to the three operations.
  • All three operations must run in average O(1).

The call volume means any O(n) operation (linear search, list remove) turns the worst case quadratic.

Think about it first

Hint 1 Which single operation does a hash set fail at, and which does a plain list fail at? What if you kept both?
Hint 2 `getRandom` wants index-based access into a compact array. The painful part is deleting from the middle of that array. Which array position is the *only* one you can delete from in O(1)?
Hint 3 Keep a list of values plus a dict value → index. To remove: look up the value's index, copy the *last* list element into that slot, update the dict for the moved element, then pop the tail. Order is destroyed — but a set doesn't care.
Your workspace Not runnable by design — this is your interview scratchpad. Saved on this device.