Open In App

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

Last Updated : 19 Apr, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

Design a data structure that supports the following operations in O(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 the current set of elements 

We can use hashing to support the first 3 operations in O(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 O(1) amortized time complexity. To implement getRandom(), we can 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. In the hash table, x is added as the key, and the 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++
#include <bits/stdc++.h>
using namespace std;

class myStructure {
    vector<int> arr;
    unordered_map<int, int> Map;

public:
    void insert(int x)
    {
        if (Map.find(x) != Map.end())
            return;
        int index = arr.size();
        arr.push_back(x);
        Map.insert({ x, index });
    }

    void remove(int x)
    {
        if (Map.find(x) == Map.end())
            return;
        int index = Map.at(x);
        Map.erase(x);
        if (index != arr.size() - 1) {
            int last = arr.size() - 1;
            swap(arr[index], arr[last]);
            if (last != index) {
                Map[arr[index]] = index;
            }
        }
        arr.pop_back();
    }

    int search(int x)
    {
        if (Map.find(x) != Map.end())
            return Map.at(x);
        return -1;
    }

    int getRandom()
    {
        srand(time(NULL));
        int random_index = rand() % arr.size();
        return arr[random_index];
    }
};

int main()
{
    myStructure ds;
    ds.insert(10);
    ds.insert(20);
    ds.insert(30);
    ds.insert(40);
    cout << ds.search(30) << endl;
    ds.remove(40);
    ds.insert(50);
    cout << ds.search(50) << endl;
    cout << ds.getRandom() << endl;
    return 0;
}

// This code is modified by Susobhan Akhuli
Java
import java.util.*;

class MyStructure {
    List<Integer> arr = new ArrayList<>();
    Map<Integer, Integer> map = new HashMap<>();

    public void insert(int x)
    {
        if (!map.containsKey(x)) {
            int index = arr.size();
            arr.add(x);
            map.put(x, index);
        }
    }

    public void remove(int x)
    {
        if (map.containsKey(x)) {
            int index = map.get(x);
            map.remove(x);
            if (index != arr.size() - 1) {
                int last = arr.size() - 1;
                Collections.swap(arr, index, last);
                if (last != index) {
                    map.put(arr.get(index), index);
                }
            }
            arr.remove(arr.size() - 1);
        }
    }

    public int search(int x)
    {
        return map.getOrDefault(x, -1);
    }

    public int getRandom()
    {
        Random rand = new Random();
        int randomIndex = rand.nextInt(arr.size());
        return arr.get(randomIndex);
    }
}

public class Main {
    public static void main(String[] args)
    {
        MyStructure ds = new MyStructure();
        ds.insert(10);
        ds.insert(20);
        ds.insert(30);
        ds.insert(40);
        System.out.println(ds.search(30));
        ds.remove(40);
        ds.insert(50);
        System.out.println(ds.search(50));
        System.out.println(ds.getRandom());
    }
}

// This code is modified by Susobhan Akhuli
Python3
import random

class MyStructure:
    def __init__(self):
        self.arr = []
        self.map = {}
        self.size=0

    def insert(self, x):
        if x not in self.map:
            index = self.size
            self.arr.append(x)
            self.size+=1
            self.map[x] = index

    def remove(self, x):
        if x in self.map:
            index = self.map[x]
            del self.map[x]
            if index != self.size - 1:
                last = self.size - 1
                self.arr[index], self.arr[last] = self.arr[last], self.arr[index]
                if last != index:
                    self.map[self.arr[index]] = index
            self.arr.pop()
            self.size-=1

    def search(self, x):
        return self.map.get(x, -1)

    def getRandom(self):
        random_index = random.randint(0, self.size - 1)
        return self.arr[random_index]

ds = MyStructure()
ds.insert(10)
ds.insert(20)
ds.insert(30)
ds.insert(40)
print(ds.search(30))
ds.remove(40)
ds.insert(50)
print(ds.search(50))
print(ds.getRandom())

# This code is modified by Susobhan Akhuli
C#
using System;
using System.Collections.Generic;

class MyStructure {
    List<int> arr = new List<int>();
    Dictionary<int, int> map = new Dictionary<int, int>();

    public void insert(int x)
    {
        if (!map.ContainsKey(x)) {
            int index = arr.Count;
            arr.Add(x);
            map.Add(x, index);
        }
    }

    public void Remove(int x)
    {
        if (map.ContainsKey(x)) {
            int index = map[x];
            map.Remove(x);
            if (index != arr.Count - 1) {
                int last = arr.Count - 1;
                arr[index] = arr[last];
                if (last != index) {
                    map[arr[index]] = index;
                }
            }
            arr.RemoveAt(arr.Count - 1);
        }
    }

    public int Search(int x)
    {
        return map.ContainsKey(x) ? map[x] : -1;
    }

    public int GetRandom()
    {
        Random rand = new Random();
        int randomIndex = rand.Next(arr.Count);
        return arr[randomIndex];
    }
}

class MainClass {
    public static void Main(string[] args)
    {
        MyStructure ds = new MyStructure();
        ds.insert(10);
        ds.insert(20);
        ds.insert(30);
        ds.insert(40);
        Console.WriteLine(ds.Search(30));
        ds.Remove(40);
        ds.insert(50);
        Console.WriteLine(ds.Search(50));
        Console.WriteLine(ds.GetRandom());
    }
}

// This code is modified by Susobhan Akhuli
JavaScript
class MyStructure {
    constructor() {
        this.arr = [];
        this.map = new Map();
    }

    insert(x) {
        if (!this.map.has(x)) {
            let index = this.arr.length;
            this.arr.push(x);
            this.map.set(x, index);
        }
    }

    remove(x) {
        if (this.map.has(x)) {
            let index = this.map.get(x);
            this.map.delete(x);
            if (index !== this.arr.length - 1) {
                let last = this.arr.length - 1;
                this.arr[index] = this.arr[last];
                if (last != index) {
                    this.map.set(this.arr[index], index);
                }
            }
            this.arr.pop();
        }
    }

    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.insert(10);
ds.insert(20);
ds.insert(30);
ds.insert(40);
console.log(ds.search(30));
ds.remove(40);
ds.insert(50);
console.log(ds.search(50));
console.log(ds.getRandom());

// This code is modified by Susobhan Akhuli

Output
2
3
50

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



Previous Article
Next Article

Similar Reads

Design a data structure that supports insert, delete, getRandom in O(1) with duplicates
Design a Data Structure that can support the following operations in O(1) Time Complexity. insert(x): Inserts x in the data structure. Returns True if x was not present and False if it was already present.remove(x): Removes x from the data structure, if present.getRandom(): Returns any value present in the stream randomly. The probability of each e
9 min read
Design a structure which supports insertion and first non-repeating element in O(1) time
Design a Data structure which supports insertion and first non-repeating element in O(1) time. Operations that are supported by the data structure: Insertion: Insert a element into the data structure.First non-repeating Element: First non-repeating element into the array. Note: If there is no non-repeating element in the array then print -1. Consid
12 min read
Design a dynamic stack using arrays that supports getMin() in O(1) time and O(1) extra space
Design a special dynamic Stack using an array that supports all the stack operations such as push(), pop(), peek(), isEmpty(), and getMin() operations in constant Time and Space complexities. Examples: Assuming the right to left orientation as the top to bottom orientation and performing the operations: Push(10): 10 is added to the top of the stack
15+ min read
Design a stack that supports getMin() in O(1) time and O(1) extra space
Design a Data Structure SpecialStack that supports all the stack operations like push(), pop(), isEmpty(), isFull() and an additional operation getMin() which should return minimum element from the SpecialStack. All these operations of SpecialStack must have a time and space complexity of O(1). Note: To implement SpecialStack, you should only use s
15+ min read
Trie Data Structure | Insert and Search
The Trie data structure is a tree-like data structure used for storing a dynamic set of strings. It is commonly used for efficient retrieval and storage of keys in a large dataset. The structure supports operations such as insertion, search, and deletion of keys, making it a valuable tool in fields like computer science and information retrieval. I
14 min read
Implementation of Search, Insert and Delete in Treap
We strongly recommend to refer set 1 as a prerequisite of this post.Treap (A Randomized Binary Search Tree)In this post, implementations of search, insert and delete are discussed.Search: Same as standard BST search. Priority is not considered for search. C/C++ Code // C function to search a given key in a given BST TreapNode* search(TreapNode* roo
15+ min read
Search, Insert, and Delete in an Unsorted Array | Array Operations
In this post, a program to search, insert, and delete operations in an unsorted array is discussed. Search Operation:In an unsorted array, the search operation can be performed by linear traversal from the first element to the last element. Coding implementation of the search operation: C/C++ Code // C++ program to implement linear // search in uns
15+ min read
Search, Insert, and Delete in an Sorted Array | Array Operations
How to Search in a Sorted Array? In a sorted array, the search operation can be performed by using binary search. Below is the implementation of the above approach: C/C++ Code // C++ program to implement binary search in sorted array #include &lt;bits/stdc++.h&gt; using namespace std; int binarySearch(int arr[], int low, int high, int key) { if (hi
15+ min read
Minimum time to write characters using insert, delete and copy operation
We need to write N same characters on a screen and each time we can insert a character, delete the last character and copy and paste all written characters i.e. after copy operation count of total written character will become twice. Now we are given time for insertion, deletion and copying. We need to output minimum time to write N characters on t
8 min read
Efficiently design Insert, Delete and Median queries on a set
Given an empty set initially and a number of queries on it, each possibly of the following types: Insert - Insert a new element ‘x’.Delete - Delete an existing element ‘x’.Median - Print the median element of the numbers currently in the set Example: Input : Insert 1 Insert 4 Insert 7 Median Output : The first three queries should insert 1, 4 and 7
15 min read
three90RightbarBannerImg