Most frequent element in Array after replacing given index by K for Q queries

Given an array arr[] of size N, and Q queries of the form {i, k} for which, the task is to print the most frequent element in the array after replacing arr[i] by k.
Example : 

Input: arr[] = {2, 2, 2, 3, 3}, Querry = {{0, 3}, {4, 2}, {0, 4}} 
Output: 3 2 2 
First query: Setting arr[0] = 3 modifies arr[] = {3, 2, 2, 3, 3}. So, 3 has max frequency. 
Second query: Setting arr[4] = 2, modifies arr[] = {3, 2, 2, 3, 2}. So, 2 has max frequency. 
Third query: Setting arr[0] = 4, modifies arr[] = {4, 2, 2, 3, 2}. So, 2 has max frequency

Input: arr[] = {1, 2, 3, 4, 3, 3} Querry = {{0, 2}, {3, 2}, {2, 4}} 
Output: 3 2 2 

Naive Approach: 
For every query, replace arr[i] by K, and traverse over the whole array and count the frequency of every array element and print the most frequent of them. 
Time Complexity: O(N * Q) 
Auxiliary Space: O(N)

Efficient Approach: 
The above approach can be optimized by precomputing the frequencies of every array element and maintain frequency-array element pairings in a set to obtain the most frequent element in O(1). Follow the steps below to solve the problem: 

  1. Initialize a map to store frequencies of all array elements, and a set of pairs to store frequency-element pairings. In the set, store the frequencies as negative. This ensures that the first pair stored at the beginning of the set, i.e. s.begin(), is the {-(maximum frequency), most frequent element} pairing.
  2. For every query, while removing the array element at ith index, do the following tasks: 
    • Find the frequency of arr[i] from the map, that is mp[arr[i]].
    • Remove the pair {-mp[arr[i]], arr[i]} from the set.
    • Update the set after decreasing the frequency of arr[i] by inserting {-(mp[arr[i] – 1), arr[i]} into the set.
    • Decrease the frequency of arr[i] in the map.
    • To insert K into the array for every query, do the following: 
      • Find the frequency of K from the map, that is mp[K].
      • Remove the pair {-mp[K], K} from the set.
      • Update the set after increasing the frequency of K by inserting {-(mp[K] + 1), K} into the set.
      • Increase the frequency of K in the map.
    • Finally for each query, extract the pair at the beginning of the set. The first element in the set denotes -(maximum frequency). Hence, the second element will be the most frequent element. Print the second element of the pair.

Below is the implementation of the above approach:



C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ program to find the most 
// frequent element after every 
// update query on the array 
  
#include <bits/stdc++.h> 
using namespace std; 
  
typedef long long int ll; 
  
// Function to print the most 
// frequent element of array 
// along with update querry 
void mostFrequent(ll arr[], ll n, ll m, 
                vector<vector<ll> > q) 
    ll i; 
  
    // Stores element->fequencies 
    // mappings 
    map<ll, ll> mp; 
  
    for (i = 0; i < n; i++) 
        mp[arr[i]] += 1; 
  
    // Stores frequencies->element 
    // mappings 
    set<pair<ll, ll> > s; 
  
    // Store the frequencies in 
    // negative 
    for (auto it : mp) { 
        s.insert(make_pair(-(it.second), 
                        it.first)); 
    
  
    for (i = 0; i < m; i++) { 
  
        // Index to be modified 
        ll j = q[i][0]; 
  
        // Value to be inserted 
        ll k = q[i][1]; 
  
        // Store the frequency of 
        // arr[j] and k 
        auto it = mp.find(arr[j]); 
        auto it2 = mp.find(k); 
  
        // Remove mapping of arr[j] 
        // with previous frequency 
        s.erase(make_pair(-(it->second), 
                        it->first)); 
  
        // Update mapping with new 
        // frequency 
        s.insert(make_pair(-((it->second) 
                            - 1), 
                        it->first)); 
  
        // Update frequency of arr[j] 
        // in the map 
        mp[arr[j]]--; 
  
        // Remove mapping of k 
        // with previous frequency 
        s.erase(make_pair(-(it2->second), 
                        it2->first)); 
  
        // Update mapping of k 
        // with previous frequency 
        s.insert(make_pair(-((it2->second) 
                            + 1), 
                        it2->first)); 
  
        // Update frequency of k 
        mp[k]++; 
  
        // Replace arr[j] by k 
        arr[j] = k; 
  
        // Display maximum frequent element 
        cout << (*s.begin()).second << " "
    
// Driver Code 
int main() 
  
    ll i, N, Q; 
    N = 5; 
    Q = 3; 
    ll arr[] = { 2, 2, 2, 3, 3 }; 
    vector<vector<ll> > querry = { 
        { 0, 3 }, 
        { 4, 2 }, 
        { 0, 4 } 
    }; 
  
    mostFrequent(arr, N, Q, querry); 

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java program to find the most 
// frequent element after every 
// update query on the array 
import java.util.*;
import java.io.*;
  
class GFG{
      
// Pair class represents
// a pair of elements
static class Pair
{
    int first, second;
    Pair(int f,int s)
    {
        first = f;
        second = s;
    }
}
  
// Function to print the most 
// frequent element of array 
// along with update querry 
static void mostFrequent(int arr[], int n, int m, 
                         ArrayList<Pair> q) 
    int i; 
  
    // Stores element->fequencies 
    // mappings 
    HashMap<Integer, Integer> map = new HashMap<>();
    HashMap<Integer, Pair> map1 = new HashMap<>();
      
    for(i = 0; i < n; i++) 
    {
        if(!map.containsKey(arr[i]))
            map.put(arr[i], 1);
        else
            map.put(arr[i], map.get(arr[i]) + 1);
    
  
    // Stores frequencies->element 
    // mappings 
    TreeSet<Pair> set = new TreeSet<>(
                        new Comparator<Pair>()
    {
        public int compare(Pair p1, Pair p2)
        {
            return p2.first - p1.first;
        }
    });
  
    // Store the frequencies in 
    // bigger to smaller
    for(Map.Entry<Integer, 
                  Integer> entry : map.entrySet())
    
        Pair p = new Pair(entry.getValue(), 
                          entry.getKey());
        set.add(p);
        map1.put(entry.getKey(), p);
    
  
    for(i = 0; i < m; i++)
    
          
        // Index to be modified 
        int j = q.get(i).first;
  
        // Value to be inserted 
        int k = q.get(i).second; 
          
        // Insert the new Pair
        // with value k if it was
        // not inserted
        if(map1.get(k) == null)
        {
            Pair p = new Pair(0, k);
            map1.put(k, p);
            set.add(p);
        }
          
        // Get the Pairs of 
        // arr[j] and k 
        Pair p1 = map1.get(arr[j]); 
        set.remove(p1);
        Pair p2 = map1.get(k);
        set.remove(p2);
          
        // Decrease the frequency of 
        // mapping with value arr[j]
        p1.first--;
        set.add(p1);
  
        // Update frequency of arr[j] 
        // in the map 
        map.put(arr[j], map.get(arr[j]) - 1); 
  
        // Increase the frequency of 
        // mapping with value k
        p2.first++;
        set.add(p2);
          
        // Update frequency of k 
        if(map.containsKey(k))
            map.put(k, map.get(k) + 1); 
        else
            map.put(k, 1);
  
        // Replace arr[j] by k 
        arr[j] = k; 
  
        // Display maximum frequent element 
        System.out.print(
            set.iterator().next().second + " "); 
    
  
// Driver Code 
public static void main(String []args)
    int i, N, Q; 
    N = 5
    Q = 3
    int arr[] = { 2, 2, 2, 3, 3 }; 
      
    ArrayList<Pair> query = new ArrayList<>();
    query.add(new Pair(0, 3));
    query.add(new Pair(4, 2));
    query.add(new Pair(0, 4));
      
    mostFrequent(arr, N, Q, query); 
}
  
// This code is contributed by Ganeshchowdharysadanala

chevron_right



Output:

3 2 2 

Time Complexity: O(N + (Q * LogN)) 
Auxiliary Space: O(N)
 

competitive-programming-img




My Personal Notes arrow_drop_up

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.