Queries to insert, delete one occurrence of a number and print the least and most frequent element

Given Q queries of type 1, 2, 3 and 4 as described below.

The task is to write a program to perform all the above queries.

Examples:

Input:
Query1: 1 6
Query2: 1 6
Query3: 1 7
Query4: 3
Query5: 1 7
Query6: 2 7
Query7: 1 7
Query8: 3
Query9: 4

Output:
7
7
6



While answering Query4, the frequency of 6 is 2 and that of
7 is 1, hence the least frequent element is 7.
In Query8, the least frequent element is 6 and 7, so print the largest.
In Query9, the most frequent element is 6 and 7, so print the smallest.

A naive approach is to use any Data-Structures(array, vector, ..) and store all the elements. Using a hash-table, the frequency of every element can be stored. While processing the Query of type-2, delete one occurrence of that element from the DS in which the element has been stored. The queries of type-3 and type-4 can be answered by traversing the hash-table. The time complexity will be O(N) per query, where N is the number of elements till then in the DS.

An efficient approach will be to use set container to answer every query. Using two sets, one hash-table the above problem can be solved in O(log n) per query. Two sets s1 and s2 are used, one stores the {num, frequency}, while the other stores the {frequency, number}. A hash-map is used which stores the frequency of each number. Design the set s2 using operator overloading such that it is sorted in ascending order of the first elements. If the first element appears to be same of one or more element, the set will be sorted in descending order of the second elements. The user-defined operating-overloading function thus will be:

bool operator b.second;          
 return a.first Note: Operator overloading only works with user-defined 
data-types. pr is a struct which has first and second as two integers. 

Below is the algorithm to solve query of every type:

Below is the implementation of the above approach:

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ program for performing 
// Queries of insert, delete one
//  occurrence of a number and 
// print the least and most frequent element
#include <bits/stdc++.h>
using namespace std;
  
// user-defined data-types
struct pr {
    int first;
    int second;
};
  
// user-defined function to
// design a set
bool operator<(pr a, pr b)
{
    if (a.first == b.first)
        return a.second > b.second;
    return a.first < b.first;
}
  
// declare a user-defined set
set<pr> s1, s2;
  
// hash map 
unordered_map<int, int> m;
  
// Function to process the query
// of type-1
void type1(int num)
{
  
    // if the element is already there
    if (m[num]) {
  
        // get the frequency of the element
        int cnt = m[num];
  
        // returns an iterator pointing to
        // position where the pair is
        auto it1 = s1.find({ num, cnt });
        auto it2 = s2.find({ cnt, num });
  
        // deletes the pair from sets
        s1.erase(it1);
        s2.erase(it2);
  
        // re-insert the pair by increasing
        // frequency
        s1.insert({ num, m[num] + 1 });
        s2.insert({ m[num] + 1, num });
    }
  
    // if the element is not there in the list
    else {
  
        // insert the element with frequency 1
        s1.insert({ num, 1 });
        s2.insert({ 1, num });
    }
  
    // increase the count in hash-table
    m[num] += 1;
}
  
// Function to process the query
// of type-2
void type2(int num)
{
    // if the element exists
    if (m[num]) {
  
        // get the frequency of the element
        int cnt = m[num];
  
        // returns an iterator pointing to
        // position where the pair is
        auto it1 = s1.find({ num, cnt });
        auto it2 = s2.find({ cnt, num });
  
        // deletes the pair from sets
        s1.erase(it1);
        s2.erase(it2);
  
        // re-insert the pair by increasing
        // frequency
        s1.insert({ num, m[num] - 1 });
        s2.insert({ m[num] - 1, num });
  
        // decrease the count
        m[num] -= 1;
    }
}
  
// Function to process the query
// of type-3
int type3()
{
    // if the set is not empty
    // return the first element
    if (!s1.empty()) {
        auto it = s2.begin();
        return it->second;
    }
  
    else
        return -1;
}
  
// Function to process the query
// of type-4
int type4()
{
  
    // if the set is not empty
    // return the last element
    if (!s1.empty()) {
        auto it = s2.rbegin();
        return it->second;
    }
  
    else
        return -1;
}
// Driver Code
int main()
{
  
    // Queries
  
    // inserts 6, 6 and 7
    type1(6);
    type1(6);
    type1(7);
  
    // print the answer to query of type3
    cout << type3() << endl;
  
    // inserts 7
    type1(7);
  
    // deletes one occurrence of 7
    type2(7);
  
    // inserts 7
    type1(7);
  
    // print the answer to query of type3
    cout << type3() << endl;
  
    // print the answer to query of type4
    cout << type4() << endl;
  
    return 0;
}
chevron_right

Output:
7
7
6

Time Complexity: O(log N) per query.
Auxiliary Space: O(N)

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.





Check out this Author's contributed articles.

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.



Improved By : nidhi_biet

Article Tags :
Practice Tags :