Open In App

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

Improve
Improve
Improve
Like Article
Like
Save Article
Save
Share
Report issue
Report

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

  • Type-1: Insert a number to the list.
  • Type-2: Delete only one occurrence of a number if exists.
  • Type-3: Print the least frequent element, if multiple elements exist then print the greatest among them.
  • Type-4: Print the most frequent element, if multiple elements exist then print the smallest among them.

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: 


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<(pr a, pr b) {
 if(a.first == b.first) return a.second > b.second;          
 return a.first < b.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: 
 

  • Type1: Check using hash-table if the element exists. If it does not exist, then mark the number in hash-table. Insert {num, 1} in set s1 and {1, num} in set2 using insert(). If it exists previously, then get the frequency from hash-table and delete {num, frequency} from set1 and {frequency, num} from set2 using find() and erase() function. Insert {num, frequency+1} in set1 and {frequency+1, num} in set2. Also, increase the count in hash-table.
  • Type2: Follow the same process as above in query type1. Only difference is to decrease the count in hash-table and insert {num, frequency-1} in set1 and {frequency-1, num} in set2.
  • Type3: Print the beginning element which can be obtained using begin() function, as the set has been designed in such a way that begin() returns the least frequent element. If there are more than one, then it returns the largest.
  • Type4: Print the last element in the set which can be obtained using rbegin() function in set.

Below is the implementation of the above approach: 
 

CPP




// 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;
}


Java




// Java code
import java.util.*;
 
// user-defined data-types
class Pr{
  int first;
  int second;
}
 
// user-defined function to
// design a set
class MyComparator implements Comparator<Pr> {
  public int compare(Pr a, Pr b){
    if (a.first == b.first)
      return a.second > b.second ? 1 : -1;
    return a.first < b.first ? -1 : 1;
  }
}
 
// declare a user-defined set
TreeSet<Pr> s1 = new TreeSet<Pr>(new MyComparator());
TreeSet<Pr> s2 = new TreeSet<Pr>(new MyComparator());
 
// hash map
Map<Integer, Integer> m = new HashMap<>();
 
// Function to process the query
// of type-1
void type1(int num)
{
 
  // if the element is already there
  if (m.containsKey(num)) {
 
    // get the frequency of the element
    int cnt = m.get(num);
 
    // returns an iterator pointing to
    // position where the pair is
    Pr key = new Pr();
    key.first = num;
    key.second = cnt;
    Pr it1 = s1.ceiling(key);
    Pr it2 = s2.ceiling(key);
 
    // deletes the pair from sets
    s1.remove(it1);
    s2.remove(it2);
 
    // re-insert the pair by increasing
    // frequency
    Pr key1 = new Pr();
    key1.first = num;
    key1.second = m.get(num) + 1;
    s1.add(key1);
 
    Pr key2 = new Pr();
    key2.first = m.get(num) + 1;
    key2.second = num;
    s2.add(key2);
  }
 
  // if the element is not there in the list
  else {
 
    // insert the element with frequency 1
    Pr key1 = new Pr();
    key1.first = num;
    key1.second = 1;
    s1.add(key1);
 
    Pr key2 = new Pr();
    key2.first = 1;
    key2.second = num;
    s2.add(key2);
  }
 
  // increase the count in hash-table
  m.put(num, m.getOrDefault(num, 0) + 1);
}
 
// Function to process the query
// of type-2
void type2(int num)
{
  // if the element exists
  if (m.containsKey(num)) {
 
    // get the frequency of the element
    int cnt = m.get(num);
 
    // returns an iterator pointing to
    // position where the pair is
    Pr key = new Pr();
    key.first = num;
    key.second = cnt;
    Pr it1 = s1.ceiling(key);
    Pr it2 = s2.ceiling(key);
 
    // deletes the pair from sets
    s1.remove(it1);
    s2.remove(it2);
 
    // re-insert the pair by increasing
    // frequency
    Pr key1 = new Pr();
    key1.first = num;
    key1.second = m.get(num) - 1;
    s1.add(key1);
 
    Pr key2 = new Pr();
    key2.first = m.get(num) - 1;
    key2.second = num;
    s2.add(key2);
 
    // decrease the count
    m.put(num, m.get(num) - 1);
  }
}
 
// Function to process the query
// of type-3
int type3()
{
  // if the set is not empty
  // return the first element
  if (!s1.isEmpty()) {
    Pr it = s2.first();
    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.isEmpty()) {
    Pr it = s2.last();
    return it.second;
  }
 
  else
    return -1;
}
// Driver Code
public static void main(String[] args)
{
 
  // Queries
 
  // inserts 6, 6 and 7
  type1(6);
  type1(6);
  type1(7);
 
  // print the answer to query of type3
  System.out.println(type3());
 
  // inserts 7
  type1(7);
 
  // deletes one occurrence of 7
  type2(7);
 
  // inserts 7
  type1(7);
 
  // print the answer to query of type3
  System.out.println(type3());
 
  // print the answer to query of type4
  System.out.println(type4());
 
}
 
// This code is contributed by ishankhandelwals.


Python




from collections import namedtuple
 
pr = namedtuple('pr', ['first', 'second'])
 
def lt(a, b):
    if a.first == b.first:
        return a.second > b.second
    return a.first < b.first
 
s1, s2 = set(), set()
m = {}
 
def type1(num):
    if num in m:
        cnt = m[num]
        it1 = next(iter(filter(lambda x: x == pr(num, cnt), s1)))
        it2 = next(iter(filter(lambda x: x == pr(cnt, num), s2)))
        s1.remove(it1)
        s2.remove(it2)
        s1.add(pr(num, m[num] + 1))
        s2.add(pr(m[num] + 1, num))
    else:
        s1.add(pr(num, 1))
        s2.add(pr(1, num))
    m[num] = m.get(num, 0) + 1
 
def type2(num):
    if num in m:
        cnt = m[num]
        it1 = next(iter(filter(lambda x: x == pr(num, cnt), s1)))
        it2 = next(iter(filter(lambda x: x == pr(cnt, num), s2)))
        s1.remove(it1)
        s2.remove(it2)
        s1.add(pr(num, m[num] - 1))
        s2.add(pr(m[num] - 1, num))
        m[num] -= 1
 
def type3():
    if s1:
        it = iter(s2)
        return next(it).second
    return -1
 
def type4():
    if s1:
        it = iter(s2)
        return next(reversed(list(it))).second
    return -1
 
type1(6)
type1(6)
type1(7)
 
print(type3())
 
type1(7)
 
type2(7)
 
type1(7)
 
print(type3())
print(type4())


Javascript




// JavaScript Code
 
// user-defined data-types
let pr = {
    first: 0,
    second: 0
};
 
// declare a user-defined set
let s1 = new Set();
let s2 = new Set();
 
// hash map
let m = {};
 
// Function to process the query
// of type-1
function type1(num) {
 
    // if the element is already there
    if (num in m) {
 
        // get the frequency of the element
        let cnt = m[num];
 
        // returns an iterator pointing to
        // position where the pair is
        let it1 = s1.find({ num, cnt });
        let it2 = s2.find({ cnt, num });
 
        // deletes the pair from sets
        s1.delete(it1);
        s2.delete(it2);
 
        // re-insert the pair by increasing
        // frequency
        s1.add({ num, m[num] + 1 });
        s2.add({ m[num] + 1, num });
    }
 
    // if the element is not there in the list
    else {
 
        // insert the element with frequency 1
        s1.add({ num, 1 });
        s2.add({ 1, num });
    }
 
    // increase the count in hash-table
    m[num] += 1;
}
 
// Function to process the query
// of type-2
function type2(num) {
    // if the element exists
    if (num in m) {
 
        // get the frequency of the element
        let cnt = m[num];
 
        // returns an iterator pointing to
        // position where the pair is
        let it1 = s1.find({ num, cnt });
        let it2 = s2.find({ cnt, num });
 
        // deletes the pair from sets
        s1.delete(it1);
        s2.delete(it2);
 
        // re-insert the pair by increasing
        // frequency
        s1.add({ num, m[num] - 1 });
        s2.add({ m[num] - 1, num });
 
        // decrease the count
        m[num] -= 1;
    }
}
 
// Function to process the query
// of type-3
function type3() {
    // if the set is not empty
    // return the first element
    if (!s1.empty()) {
        let it = s2.first();
        return it.second;
    }
 
    else
        return -1;
}
 
// Function to process the query
// of type-4
function type4() {
 
    // if the set is not empty
    // return the last element
    if (!s1.empty()) {
        let it = s2.last();
        return it.second;
    }
 
    else
        return -1;
}
 
// Driver Code
function main() {
 
    // Queries
 
    // inserts 6, 6 and 7
    type1(6);
    type1(6);
    type1(7);
 
    // print the answer to query of type3
    console.log(type3());
 
    // inserts 7
    type1(7);
 
    // deletes one occurrence of 7
    type2(7);
 
    // inserts 7
    type1(7);
 
    // print the answer to query of type3
    console.log(type3());
 
    // print the answer to query of type4
    console.log(type4());
}
 
main();
 
// This code is contributed by ishankhandelwals.


C#




// C# program for performing
// Queries of insert, delete one
//  occurrence of a number and
// print the least and most frequent element
using System;
using System.Collections.Generic;
 
// user-defined data-types
public struct pr
{
    public int first;
    public int second;
}
 
// user-defined function to
// design a set
public class Sortbyfirst : IComparer<pr>
{
    public int Compare(pr a, pr b)
    {
        if (a.first == b.first)
            return a.second > b.second ? 1 : -1;
        return a.first < b.first ? -1 : 1;
    }
}
 
// declare a user-defined set
public static SortedSet<pr> s1 = new SortedSet<pr>(new Sortbyfirst());
public static SortedSet<pr> s2 = new SortedSet<pr>(new Sortbyfirst());
 
// hash map
public static Dictionary<int, int> m = new Dictionary<int, int>();
 
// Function to process the query
// of type-1
public static void type1(int num)
{
 
    // if the element is already there
    if (m.ContainsKey(num))
    {
 
        // get the frequency of the element
        int cnt = m[num];
 
        // returns an iterator pointing to
        // position where the pair is
        pr target1 = new pr { first = num, second = cnt };
        pr target2 = new pr { first = cnt, second = num };
 
        // deletes the pair from sets
        s1.Remove(target1);
        s2.Remove(target2);
 
        // re-insert the pair by increasing
        // frequency
        s1.Add(new pr { first = num, second = m[num] + 1 });
        s2.Add(new pr { first = m[num] + 1, second = num });
    }
 
    // if the element is not there in the list
    else
    {
 
        // insert the element with frequency 1
        s1.Add(new pr { first = num, second = 1 });
        s2.Add(new pr { first = 1, second = num });
    }
 
    // increase the count in hash-table
    m[num] += 1;
}
 
// Function to process the query
// of type-2
public static void type2(int num)
{
    // if the element exists
    if (m.ContainsKey(num))
    {
 
        // get the frequency of the element
        int cnt = m[num];
 
        // returns an iterator pointing to
        // position where the pair is
        pr target1 = new pr { first = num, second = cnt };
        pr target2 = new pr { first = cnt, second = num };
 
        // deletes the pair from sets
        s1.Remove(target1);
        s2.Remove(target2);
 
        // re-insert the pair by increasing
        // frequency
        s1.Add(new pr { first = num, second = m[num] - 1 });
        s2.Add(new pr { first = m[num] - 1, second = num });
 
        // decrease the count
        m[num] -= 1;
    }
}
 
// Function to process the query
// of type-3
public static int type3()
{
    // if the set is not empty
    // return the first element
    if (s1.Count != 0)
    {
        return s2.Min.second;
    }
 
    else
        return -1;
}
 
// Function to process the query
// of type-4
public static int type4()
{
 
    // if the set is not empty
    // return the last element
    if (s1.Count != 0)
    {
        return s2.Max.second;
    }
 
    else
        return -1;
}
 
// Driver Code
public static void Main()
{
 
    // Queries
 
    // inserts 6, 6 and 7
    type1(6);
    type1(6);
    type1(7);
 
    // print the answer to query of type3
    Console.WriteLine(type3());
 
    // inserts 7
    type1(7);
 
    // deletes one occurrence of 7
    type2(7);
 
    // inserts 7
    type1(7);
 
    // print the answer to query of type3
    Console.WriteLine(type3());
 
    // print the answer to query of type4
    Console.WriteLine(type4());
}
 
// This code is contributed by ishankhandelwals.


Output: 

7
7
6

 

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



Last Updated : 14 Mar, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads