Open In App
Related Articles

Design a data structure that supports insert, delete, search and getRandom in constant time

Improve Article
Improve
Save Article
Save
Like Article
Like

Design a data structure that supports the following operations in ?(1) time.

  • insert(x): Inserts an item x to the data structure if not already present.
  • remove(x): Removes item x from the data structure if present. 
  • search(x): Searches an item x in the data structure.
  • getRandom(): Returns a random element from current set of elements 

We can use hashing to support first 3 operations in ?(1) time. How to do the 4th operation? The idea is to use a resizable array (ArrayList in Java, vector in C) together with hashing. Resizable arrays support insert in ?(1) amortized time complexity. To implement getRandom(), we can simply pick a random number from 0 to size-1 (size is the number of current elements) and return the element at that index. The hash map stores array values as keys and array indexes as values.

Following are detailed operations.

  • insert(x) 
    1. Check if x is already present by doing a hash map lookup. 
    2. If not present, then insert it at the end of the array. 
    3. Add in the hash table also, x is added as key and last array index as the index.
  • remove(x) 
    1. Check if x is present by doing a hash map lookup. 
    2. If present, then find its index and remove it from a hash map. 
    3. Swap the last element with this element in an array and remove the last element. 
      Swapping is done because the last element can be removed in O(1) time. 
    4. Update index of the last element in a hash map.
  • getRandom() 
    1. Generate a random number from 0 to last index. 
    2. Return the array element at the randomly generated index.
  • search(x) 
    • Do a lookup for x in hash map.

Below is the implementation of the data structure.

C++




/* C++ program to design a DS that supports following operations
in Theta(n) time
a) Insert
b) Delete
c) Search
d) getRandom */
 
#include<bits/stdc++.h>
using namespace std;
 
// class to represent the required data structure
class myStructure
{
    // A resizable array
    vector <int> arr;
     
    // A hash where keys are array elements and values are
    // indexes in arr[]
    unordered_map <int, int> Map;
 
    public:
    // A Theta(1) function to add an element to MyDS
    // data structure
    void add(int x)
    {
        // If element is already present, then nothing to do
        if(Map.find(x) != Map.end())
            return;
             
        // Else put element at the end of arr[]
        int index = arr.size();
        arr.push_back(x);
             
        // and hashmap also
        Map.insert(std::pair<int,int>(x, index));
    }
         
    // function to remove a number to DS in O(1)
    void remove(int x)
    {
        // element not found then return
        if(Map.find(x) == Map.end())
            return;
             
        // remove element from map
        int index = Map.at(x);
        Map.erase(x);
             
        // swap with last element in arr
        // then remove element at back
        int last = arr.size() - 1;
        swap(arr[index], arr[last]);
        arr.pop_back();
             
        // Update hash table for new index of last element
        Map.at(arr[index]) = index;
    }
         
    // Returns index of element if element is present, otherwise null
    int search(int x)
    {
        if(Map.find(x) != Map.end())
        return Map.at(x);
        return -1;
    }
         
    // Returns a random element from myStructure
    int getRandom()
    {
        // Find a random index from 0 to size - 1
        srand (time(NULL));
        int random_index = rand() % arr.size();
             
        // Return element at randomly picked index
        return arr.at(random_index);
    }    
};
 
// Driver main
int main()
{
    myStructure ds;
    ds.add(10);
    ds.add(20);
    ds.add(30);
    ds.add(40);
    cout << ds.search(30) << endl;
    ds.remove(20);
    ds.add(50);
    cout << ds.search(50) << endl;
    cout << ds.getRandom() << endl;
}
 
// This code is contributed by Aditi Sharma

Java




import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
 
public class MyStructure {
 
    private ArrayList<Integer> arr; // A resizable array to hold the elements
    private Map<Integer, Integer> map; // A hash map to store the indexes of elements in arr
 
    // Constructor to initialize the array and hash map
    public MyStructure() {
        arr = new ArrayList<Integer>();
        map = new HashMap<Integer, Integer>();
    }
 
    // Method to add an element to the data structure
    public void add(int x) {
        // If element is already present, do nothing
        if (!map.containsKey(x)) {
            // Else add element to the end of the array
            int index = arr.size();
            arr.add(x);
            // And store its index in the hash map
            map.put(x, index);
        }
    }
 
    // Method to remove an element from the data structure
    public void remove(int x) {
        // If element is not present, do nothing
        if (map.containsKey(x)) {
            // Else remove element from the hash map and get its index in the array
            int index = map.get(x);
            map.remove(x);
            // Swap the element with the last element in the array and remove the last element
            int last = arr.size() - 1;
            arr.set(index, arr.get(last));
            arr.remove(last);
            // Update the hash map with the new index of the element that was swapped with the last element
            map.put(arr.get(index), index);
        }
    }
 
    // Method to search for an element in the data structure
    public int search(int x) {
        // If element is present, return its index in the array from the hash map
        if (map.containsKey(x)) {
            return map.get(x);
        }
        // Else return -1
        return -1;
    }
 
    // Method to get a random element from the data structure
    public int getRandom() {
        Random rand = new Random();
        // Generate a random index from 0 to size - 1 of the array
        int randomIndex = rand.nextInt(arr.size());
        // Return the element at the randomly picked index
        return arr.get(randomIndex);
    }
 
    // Main method to test the data structure
    public static void main(String[] args) {
        MyStructure ds = new MyStructure();
        ds.add(10);
        ds.add(20);
        ds.add(30);
        ds.add(40);
        System.out.println(ds.search(30)); // Output: 2
        ds.remove(20);
        ds.add(50);
        System.out.println(ds.search(50)); // Output: 3
        System.out.println(ds.getRandom()); // Output: A random element from the array
    }
}
// This code is contributed by lakshyadeeppatel

Python3




'''
Python program to design a DS that
supports following operations
in Theta(n) time:
a) Insert
b) Delete
c) Search
d) getRandom
'''
import random
 
# Class to represent the required
# data structure
class MyDS:
 
    # Constructor (creates a list and a hash)
    def __init__(self):
         
        # A resizable array
        self.arr = []
 
        # A hash where keys are lists elements
        # and values are indexes of the list
        self.hashd = {}
 
    # A Theta(1) function to add an element
    # to MyDS data structure
    def add(self, x):
         
        # If element is already present,
        # then nothing has to be done
        if x in self.hashd:
            return
 
        # Else put element at
        # the end of the list
        s = len(self.arr)
        self.arr.append(x)
 
        # Also put it into hash
        self.hashd[x] = s
 
    # A Theta(1) function to remove an element
    # from MyDS data structure
    def remove(self, x):
         
        # Check if element is present
        index = self.hashd.get(x, None)
        if index == None:
            return
 
        # If present, then remove
        # element from hash
        del self.hashd[x]
 
        # Swap element with last element
        # so that removal from the list
        # can be done in O(1) time
        size = len(self.arr)
        last = self.arr[size - 1]
        self.arr[index], \
        self.arr[size - 1] = self.arr[size - 1], \
                             self.arr[index]
 
        # Remove last element (This is O(1))
        del self.arr[-1]
 
        # Update hash table for
        # new index of last element
        self.hashd[last] = index
 
    # Returns a random element from MyDS
    def getRandom(self):
         
         
        # Find a random index from 0 to size - 1
        index = random.randrange(0, len(self.arr))
 
        # Return element at randomly picked index
        return self.arr[index]
 
    # Returns index of element
    # if element is present,
    # otherwise none
    def search(self, x):
        return self.hashd.get(x, None)
 
# Driver Code
if __name__=="__main__":
    ds = MyDS()
    ds.add(10)
    ds.add(20)
    ds.add(30)
    ds.add(40)
    print(ds.search(30))
    ds.remove(20)
    ds.add(50)
    print(ds.search(50))
    print(ds.getRandom())
 
# This code is contributed
# by Saurabh Singh

C#




using System;
using System.Collections.Generic;
 
public class MyStructure
{
 
  private List<int> arr; // A resizable array to hold the elements
  private Dictionary<int, int> map; // A hash map to store the indexes of elements in arr
 
  // Constructor to initialize the array and hash map
  public MyStructure()
  {
    arr = new List<int>();
    map = new Dictionary<int, int>();
  }
 
  // Method to add an element to the data structure
  public void add(int x)
  {
    // If element is already present, do nothing
    if (!map.ContainsKey(x))
    {
      // Else add element to the end of the array
      int index = arr.Count;
      arr.Add(x);
      // And store its index in the hash map
      map.Add(x, index);
    }
  }
 
  // Method to remove an element from the data structure
  public void remove(int x)
  {
    // If element is not present, do nothing
    if (map.ContainsKey(x))
    {
      // Else remove element from the hash map and get its index in the array
      int index = map[x];
      map.Remove(x);
      // Swap the element with the last element in the array and remove the last element
      int last = arr.Count - 1;
      arr[index] = arr[last];
      arr.RemoveAt(last);
      // Update the hash map with the new index of the element that was swapped with the last element
      map[arr[index]] = index;
    }
  }
 
  // Method to search for an element in the data structure
  public int search(int x)
  {
    // If element is present, return its index in the array from the hash map
    if (map.ContainsKey(x))
    {
      return map[x];
    }
    // Else return -1
    return -1;
  }
 
  // Method to get a random element from the data structure
  public int getRandom()
  {
    Random rand = new Random();
    // Generate a random index from 0 to size - 1 of the array
    int randomIndex = rand.Next(arr.Count);
    // Return the element at the randomly picked index
    return arr[randomIndex];
  }
 
  // Main method to test the data structure
  public static void Main(string[] args)
  {
    MyStructure ds = new MyStructure();
    ds.add(10);
    ds.add(20);
    ds.add(30);
    ds.add(40);
    Console.WriteLine(ds.search(30)); // Output: 2
    ds.remove(20);
    ds.add(50);
    Console.WriteLine(ds.search(50)); // Output: 3
    Console.WriteLine(ds.getRandom()); // Output: A random element from the array
  }
}
 
// This code is contributed by akashish__

Javascript




class myStructure {
  constructor() {
    this.arr = [];
    this.Map = new Map();
  }
 
  add(x) {
    if (this.Map.has(x)) return;
    let index = this.arr.length;
    this.arr.push(x);
    this.Map.set(x, index);
  }
 
  remove(x) {
    if (!this.Map.has(x)) return;
    let index = this.Map.get(x);
    this.Map.delete(x);
    let last = this.arr.length - 1;
    [this.arr[index], this.arr[last]] = [this.arr[last], this.arr[index]];
    this.arr.pop();
    this.Map.set(this.arr[index], index);
  }
 
  search(x) {
    return this.Map.has(x) ? this.Map.get(x) : -1;
  }
 
  getRandom() {
    let randomIndex = Math.floor(Math.random() * this.arr.length);
    return this.arr[randomIndex];
  }
}
 
let ds = new myStructure();
ds.add(10);
ds.add(20);
ds.add(30);
ds.add(40);
console.log(ds.search(30));
ds.remove(20);
ds.add(50);
console.log(ds.search(50));
console.log(ds.getRandom());

Output

2
3
30

Time Complexity: O(1) for all operations.
Space Complexity: O(n) for storing the elements in the data structure.

This article is contributed by Manish Gupta. Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above. 


Last Updated : 17 Mar, 2023
Like Article
Save Article
Similar Reads
Related Tutorials