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 element being returned should be**linearly proportional**to the number of same valued elements the stream contains.

**Approach:** In the previous article, we have already discussed an approach for this kind of data structure. However, the previous data structure worked well only for unique values. In this article, we will design a data structure which can handle duplicate elements also.

The approach used in this article is much similar to the previous approach, but in order to handle the duplicate elements, a map of sets is used to store the indices of the elements present in the dynamic array. Let’s understand every method independently.

**insert(int x):**- Insert x at the end of the dynamic array nums[].
- Insert the index of x (i.e.) nums.size() – 1 to
**mp[x]**. This map of sets stores all the indices of the element**x**present in the dynamic array**nums[]**.

**remove(int x):**- Check if x is present in the stream by mp.count(x). If it is absent, then return
**False**. - If x is present, the first element of the set mp[x] is deleted and its value is stored in a variable
**indexRemoved**. Now, if this element (i.e.) indexRemoved is the same as nums.length() – 1 go directly to**step 6**because this means that the element is already at the last index and that element is deleted in constant time. - If not, then in order to delete this element in constant time, this element is swapped with the last element in the dynamic array. Therefore, delete the value
**nums.size() – 1**from the**mp[nums[nums.size() – 1]]**set. - Insert the value index into mp[nums[nums.size() – 1]] set.
- Swap the elements at index nums.size() – 1 and indexRemoved of nums.
- Delete the last element from nums (Removal from the end from Dynamic Array is constant time operation).
- If the mp[val] set becomes empty, erase val from mp.
- Return
**True**

- Check if x is present in the stream by mp.count(x). If it is absent, then return
**getRandom():**- Get a random number between 0 and nums.size() – 1.
- Return the value present at this index of nums.

Below is the implementation of the above approach:

`// C++ program to design a data structure ` `// that supports insert, delete, ` `// getRandom in O(1) with duplicates ` ` ` `#include <bits/stdc++.h> ` ` ` `using` `namespace` `std; ` ` ` `class` `Stream { ` ` ` `private` `: ` ` ` `// Stores all the numbers present ` ` ` `// currently in the stream ` ` ` `vector<` `int` `> nums; ` ` ` ` ` `// Unordered ensure O(1) operation ` ` ` `unordered_map<` `int` `, unordered_set<` `int` `> > mp; ` ` ` `public` `: ` ` ` `// Function to insert values ` ` ` `// in the stream ` ` ` `bool` `insert(` `int` `val) ` ` ` `{ ` ` ` `// Inserting val to the end of array ` ` ` `nums.push_back(val); ` ` ` ` ` `// Index at which val was inserted ` ` ` `int` `index = nums.size() - 1; ` ` ` ` ` `// Inserting the index inside the ` ` ` `// set mp[val] ` ` ` `mp[val].insert(index); ` ` ` ` ` `// Return True if only one val ` ` ` `// is present in the stream ` ` ` `return` `mp[val].size() == 1; ` ` ` `} ` ` ` ` ` `// Function to remove the value ` ` ` `// from the stream ` ` ` `bool` `remove` `(` `int` `val) ` ` ` `{ ` ` ` ` ` `// If the value is not present ` ` ` `// in the stream ` ` ` `if` `(!mp.count(val)) ` ` ` `return` `0; ` ` ` ` ` `// Get the value of the first element ` ` ` `// of the mp[val] and store it ` ` ` `// in a variable named index ` ` ` `int` `index = *(mp[val].begin()); ` ` ` ` ` `// Last Index of nums ` ` ` `int` `lastIndex = nums.size() - 1; ` ` ` ` ` `// Erase the index from mp[val] set ` ` ` `mp[val].erase(index); ` ` ` ` ` `// If index == lastIndex, then the ` ` ` `// element was already deleted ` ` ` `// from the stream ` ` ` `if` `(index != lastIndex) { ` ` ` ` ` `// Delete the lastIndex from ` ` ` `// mp[nums[lastIndex]] set ` ` ` `mp[nums[lastIndex]].erase(lastIndex); ` ` ` ` ` `// Insert index into mp[nums[lastIndex]] set ` ` ` `mp[nums[lastIndex]].insert(index); ` ` ` ` ` `// Swap the values at index and lastIndex ` ` ` `swap(nums[index], nums[lastIndex]); ` ` ` `} ` ` ` ` ` `// Delete the last element from nums ` ` ` `// This operation is O(1) operation ` ` ` `nums.pop_back(); ` ` ` ` ` `// If the size of mp[val] is 0, ` ` ` `// val is absent from the stream ` ` ` `// and hence it is removed ` ` ` `if` `(mp[val].size() == 0) ` ` ` `mp.erase(val); ` ` ` `return` `1; ` ` ` `} ` ` ` ` ` `// Function to get a random number ` ` ` `// from the stream of data ` ` ` `int` `getRandom() ` ` ` `{ ` ` ` ` ` `// Get any random index from 0 to ` ` ` `// nums.length() - 1 ` ` ` `int` `randomIndex = ` `rand` `() % nums.size(); ` ` ` `// Return the value at that index ` ` ` `return` `nums[randomIndex]; ` ` ` `} ` `}; ` ` ` `// Driver code ` `int` `main() ` `{ ` ` ` ` ` `Stream myStream; ` ` ` ` ` `cout << myStream.insert(5) << endl; ` ` ` `cout << myStream.insert(6) << endl; ` ` ` `cout << myStream.insert(5) << endl; ` ` ` `cout << myStream.` `remove` `(6) << endl; ` ` ` `cout << myStream.` `remove` `(6) << endl; ` ` ` `cout << myStream.getRandom() << endl; ` ` ` ` ` `return` `0; ` `} ` |

*chevron_right*

*filter_none*

**Output:**

1 1 0 1 0 5

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the **DSA Self Paced Course** at a student-friendly price and become industry ready.

## Recommended Posts:

- Design a data structure that supports insert, delete, search and getRandom in constant time
- Efficiently design Insert, Delete and Median queries on a set
- Design an efficient data structure for given operations
- Design a Queue data structure to get minimum or maximum in O(1) time
- Treap | Set 2 (Implementation of Search, Insert and Delete)
- Gap Buffer Data Structure
- Tango Tree Data Structure
- Introduction to the Probabilistic Data Structure
- Advantages of Trie Data Structure
- Trie Data Structure using smart pointer and OOP in C++
- Data Structure for Dictionary and Spell Checker?
- Inversion Count using Policy Based Data Structure
- Ropes Data Structure (Fast String Concatenation)
- Dynamic Disjoint Set Data Structure for large range values
- Insert Operation in B-Tree
- Red-Black Tree | Set 2 (Insert)
- 2-3 Trees | (Search and Insert)
- Trie | (Insert and Search)
- Splay Tree | Set 2 (Insert)
- K Dimensional Tree | Set 1 (Search and Insert)

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.