Insert Delete GetRandom O(1) – 380. LeetCode

The LeetCode problem Insert Delete GetRandom O(1) requires implementing a data structure that supports inserting, deleting, and retrieving random element in constant time. Here’s a detail breakdown:

Imagine you have a collection of elements, and you want to perform three key operations:

1. Add a new element.

2. Remove an existing element.

3. Get a random element, all in constant time.

Brute Force Approach

import java.util.*;

class RandomizedSet {
    private List<Integer> list;

    public RandomizedSet() {
        list = new ArrayList<>();
    }

    public boolean insert(int val) {
        if (list.contains(val)) return false;
        list.add(val);
        return true;
    }

    public boolean remove(int val) {
        return list.remove((Integer) val);
    }

    public int getRandom() {
        Random random = new Random();
        return list.get(random.nextInt(list.size()));
    }
}

Insert: Uses ArrayList.add but checks contains, making it O(n) because of the linear search.

Remove: Uses ArrayList.remove, which is O(n) due to the search for the element.

GetRandom: Efficient O(1) as ArrayList.get works in constant time.


This approach is not optimal because searching for elements during insertion and deletion takes linear time.

Optimized Approach


In computer science and competitive programming, the combination of a HashMap and an ArrayList is often used for tasks that require efficient insertion, deletion, and retrieval of elements. While an ArrayList alone offers simplicity and efficiency in certain scenarios, combining it with a HashMap unlocks additional power and efficiency. Let’s dive into why this combination is so popular, particularly in coding challenges like LeetCode.

HashMap provides quick indexing and lookup.

ArrayList maintains the order and supports efficient random access.

• Together, they efficiently handle a mix of operations that would be slow if only one data structure was used.

import java.util.*;

class RandomizedSet {
    private Map<Integer, Integer> map; // Maps value -> index in ArrayList
    private List<Integer> list;       // Stores the actual values
    private Random random;

    public RandomizedSet() {
        map = new HashMap<>();
        list = new ArrayList<>();
        random = new Random();
    }

    public boolean insert(int val) {
        if (map.containsKey(val)) return false; // Value already exists
        map.put(val, list.size());             // Add value and its index
        list.add(val);                         // Add value to ArrayList
        return true;
    }

    public boolean remove(int val) {
        if (!map.containsKey(val)) return false; // Value not present
        int index = map.get(val);                // Get index of value
        int lastVal = list.get(list.size() - 1); // Get last element in list

        list.set(index, lastVal);                // Swap with last element
        map.put(lastVal, index);                 // Update index of last element

        list.remove(list.size() - 1);            // Remove last element
        map.remove(val);                         // Remove from map
        return true;
    }

    public int getRandom() {
        return list.get(random.nextInt(list.size())); // Get random element
    }
}

Line-By-Line Explanation

Step 1: Create Properties

class RandomizedSet {
    private Map<Integer, Integer> map; // Maps value -> index in ArrayList
    private List<Integer> list;       // Stores the actual values
    private Random random;

1. A HashMap (map) to map values to their indices in the list.

2. An ArrayList (list) to store the values for easy access and random retrieval.

3. A Random object (random) to generate random indices.

Step 2: Initialize Data Sructures

public RandomizedSet() {
    map = new HashMap<>();
    list = new ArrayList<>();
    random = new Random();
}
  • Sets up the data structures required for the operations (insert, remove, and getRandom).

Step 3: Insert Method

public boolean insert(int val) {
    if (map.containsKey(val)) return false; // Value already exists
    map.put(val, list.size());             // Add value and its index
    list.add(val);                         // Add value to ArrayList
    return true;
}
  • Uses map.containsKey(val) to check if the value is already in the set.
  • Adds the value to the list and updates the map with its index.

Step 4: Remove Method

public boolean remove(int val) {
    if (!map.containsKey(val)) return false; // Value not present
    int index = map.get(val);                // Get index of value
    int lastVal = list.get(list.size() - 1); // Get last element in list

    list.set(index, lastVal);                // Swap with last element
    map.put(lastVal, index);                 // Update index of last element

    list.remove(list.size() - 1);            // Remove last element
    map.remove(val);                         // Remove from map
    return true;
}
  • Verify the value is in the map using contains key
  • Gets the index of the value and the last value in the list. Value must be swapped with the last element to enable O(1) removal.
  • Overwrites the value at index with lastVal in the list and updates its index in the map.
  • Removes the last element from the list and deletes the mapping from the map.
  • Maintains a compact list without shifting element, ensuring O(1) deletion.

Step 5: getRandom Method

public int getRandom() {
    return list.get(random.nextInt(list.size())); // Get random element
}
  • Uses random.nextInt(list.size()) to generate a random integer between 0 and list.size() – 1.
  • Ensures a uniform random selection of elements.

Why This Code Works


Using a HashMap and ArrayList together is a powerful pattern in competitive programming and practical coding. While an ArrayList alone is sufficient for simple storage and access, the addition of a HashMap transforms it into a versatile data structure capable of supporting complex operations with ease. By leveraging the strengths of both, we achieve an elegant solution to problems that demand efficiency and flexibility.

Leave a Reply

Your email address will not be published. Required fields are marked *