Minimum characters required to be removed to make frequency of each character unique - GeeksforGeeks

24 Jun, 2021
Given string str, the task is to find the minimum count of characters that need to be deleted from the string such that the frequency of each character of the string is unique.
Examples:
Input: str = “ceabaacb” Output: 2 Explanation: The frequencies of each distinct character are as follows: c —> 2 e —> 1 a —> 3 b —> 2 Possible ways to make frequency of each character unique by minimum number of moves are: 
Removing both occurrences of ‘c’ modifies str to “eabaab”
Removing an occurrence of ‘c’ and ‘e’ modifies str to “abaacb”
Therefore, the minimum removals required is 2.
Input: S = “abbbcccd” Output: 2  
Approach: The problem can be solved using Greedy technique. The idea is to use Map and Priority Queue. Follow the steps below to solve the problem:
Initialize a Map, say mp, to store the frequency of each distinct character of the string.
Initialize a variable, say cntChar to store the count of characters required to be removed to make frequency of each character of the string unique.
Create a priority_queue, say pq to store the frequency of each character such that the largest frequency obtained is present at the top of the priority queue pq.
Iterate over the priority_queue until pq is empty and check if the topmost of element of pq is equal to the second topmost element of pq or not. If found to be true, then decrement the value of topmost element of pq by 1 and increment the value of cntChar by 1.
Otherwise, pop the topmost element of pq.
Finally, print the value of cntChar.
Below is the implementation of the above approach:
C++
Java
Python3
C#
Javascript
// C++ program to implement// the above approach #include <bits/stdc++.h>using namespace std; // Function to find the minimum count of// characters required to be deleted to make// frequencies of all characters uniqueint minCntCharDeletionsfrequency(string& str,                                 int N){    // Stores frequency of each    // distinct character of str    unordered_map<char, int> mp;     // Store frequency of each distinct    // character such that the largest    // frequency is present at the top    priority_queue<int> pq;     // Stores minimum count of characters    // required to be deleted to make    // frequency of each character unique    int cntChar = 0;     // Traverse the string    for (int i = 0; i < N; i++) {         // Update frequency of str[i]        mp[str[i]]++;    }     // Traverse the map    for (auto it : mp) {         // Insert current        // frequency into pq        pq.push(it.second);    }     // Traverse the priority_queue    while (!pq.empty()) {         // Stores topmost        // element of pq        int frequent            = pq.top();         // Pop the topmost element        pq.pop();         // If pq is empty        if (pq.empty()) {             // Return cntChar            return cntChar;        }         // If frequent and topmost        // element of pq are equal        if (frequent == pq.top()) {             // If frequency of the topmost            // element is greater than 1            if (frequent > 1) {                 // Insert the decremented                // value of frequent                pq.push(frequent - 1);            }             // Update cntChar            cntChar++;        }    }     return cntChar;} // Driver Codeint main(){     string str = "abbbcccd";     // Stores length of str    int N = str.length();    cout << minCntCharDeletionsfrequency(        str, N);    return 0;}
// Java program to implement// the above approachimport java.util.*;class GFG{ // Function to find the minimum count of// characters required to be deleted to make// frequencies of all characters uniquestatic int minCntCharDeletionsfrequency(char[] str,                                        int N){  // Stores frequency of each  // distinct character of str  HashMap<Character,          Integer> mp =          new HashMap<>();   // Store frequency of each distinct  // character such that the largest  // frequency is present at the top  PriorityQueue<Integer> pq =          new PriorityQueue<>((x, y) ->          Integer.compare(y, x));   // Stores minimum count of characters  // required to be deleted to make  // frequency of each character unique  int cntChar = 0;   // Traverse the String  for (int i = 0; i < N; i++)  {    // Update frequency of str[i]    if(mp.containsKey(str[i]))    {      mp.put(str[i],      mp.get(str[i]) + 1);    }    else    {      mp.put(str[i], 1);    }  }   // Traverse the map  for (Map.Entry<Character,                 Integer> it :                 mp.entrySet())  {    // Insert current    // frequency into pq    pq.add(it.getValue());  }   // Traverse the priority_queue  while (!pq.isEmpty())  {    // Stores topmost    // element of pq    int frequent = pq.peek();     // Pop the topmost element    pq.remove();     // If pq is empty    if (pq.isEmpty()) {       // Return cntChar      return cntChar;    }     // If frequent and topmost    // element of pq are equal    if (frequent == pq.peek())    {      // If frequency of the topmost      // element is greater than 1      if (frequent > 1)      {        // Insert the decremented        // value of frequent        pq.add(frequent - 1);      }       // Update cntChar      cntChar++;    }  }   return cntChar;} // Driver Codepublic static void main(String[] args){  String str = "abbbcccd";   // Stores length of str  int N = str.length();  System.out.print(minCntCharDeletionsfrequency(         str.toCharArray(), N));}} // This code is contributed by Rajput-Ji
# Python3 program to implement# the above approach # Function to find the minimum count of# characters required to be deleted to make# frequencies of all characters uniquedef minCntCharDeletionsfrequency(str, N):         # Stores frequency of each    # distinct character of str    mp = {}     # Store frequency of each distinct    # character such that the largest    # frequency is present at the top    pq = []     # Stores minimum count of characters    # required to be deleted to make    # frequency of each character unique    cntChar = 0     # Traverse the string    for i in range(N):                 # Update frequency of str[i]        mp[str[i]] = mp.get(str[i], 0) + 1             # Traverse the map    for it in mp:                 # Insert current        # frequency into pq        pq.append(mp[it])     pq = sorted(pq)         # Traverse the priority_queue    while (len(pq) > 0):                 # Stores topmost        # element of pq        frequent = pq[-1]         # Pop the topmost element        del pq[-1]         # If pq is empty        if (len(pq) == 0):                         # Return cntChar            return cntChar                     # If frequent and topmost        # element of pq are equal        if (frequent == pq[-1]):                         # If frequency of the topmost            # element is greater than 1            if (frequent > 1):                                 # Insert the decremented                # value of frequent                pq.append(frequent - 1)                             # Update cntChar            cntChar += 1                     pq = sorted(pq)             return cntChar # Driver Codeif __name__ == '__main__':         str = "abbbcccd"     # Stores length of str    N = len(str)         print(minCntCharDeletionsfrequency(str, N)) # This code is contributed by mohit kumar 29
// C# program to implement// the above approachusing System;using System.Collections.Generic; class GFG{ // Function to find the minimum count of// characters required to be deleted to make// frequencies of all characters uniquestatic int minCntCharDeletionsfrequency(char[] str,                                        int N){         // Stores frequency of each    // distinct character of str    Dictionary<char,               int> mp = new Dictionary<char,                                        int>();     // Store frequency of each distinct    // character such that the largest    // frequency is present at the top    List<int> pq = new List<int>();     // Stores minimum count of characters    // required to be deleted to make    // frequency of each character unique    int cntChar = 0;     // Traverse the String    for(int i = 0; i < N; i++)    {                 // Update frequency of str[i]        if (mp.ContainsKey(str[i]))        {            mp[str[i]]++;        }        else        {            mp.Add(str[i], 1);        }    }     // Traverse the map    foreach(KeyValuePair<char, int> it in mp)    {                 // Insert current        // frequency into pq        pq.Add(it.Value);    }    pq.Sort();    pq.Reverse();         // Traverse the priority_queue    while (pq.Count != 0)    {                 // Stores topmost        // element of pq        pq.Sort();        pq.Reverse();        int frequent = pq[0];         // Pop the topmost element        pq.RemoveAt(0);         // If pq is empty        if (pq.Count == 0)        {                         // Return cntChar            return cntChar;        }         // If frequent and topmost        // element of pq are equal        if (frequent == pq[0])        {                         // If frequency of the topmost            // element is greater than 1            if (frequent > 1)            {                                 // Insert the decremented                // value of frequent                pq.Add(frequent - 1);                pq.Sort();                // pq.Reverse();            }             // Update cntChar            cntChar++;        }    }    return cntChar;} // Driver Codepublic static void Main(String[] args){    String str = "abbbcccd";     // Stores length of str    int N = str.Length;         Console.Write(minCntCharDeletionsfrequency(        str.ToCharArray(), N));}} // This code is contributed by shikhasingrajput
<script>// Javascript program to implement// the above approach // Function to find the minimum count of// characters required to be deleted to make// frequencies of all characters uniquefunction minCntCharDeletionsfrequency(str,N){    // Stores frequency of each  // distinct character of str  let mp = new Map();    // Store frequency of each distinct  // character such that the largest  // frequency is present at the top  let pq =[];    // Stores minimum count of characters  // required to be deleted to make  // frequency of each character unique  let cntChar = 0;    // Traverse the String  for (let i = 0; i < N; i++)  {    // Update frequency of str[i]    if(mp.has(str[i]))    {      mp.set(str[i],      mp.get(str[i]) + 1);    }    else    {      mp.set(str[i], 1);    }  }    // Traverse the map  for (let [key, value] of mp.entries())  {    // Insert current    // frequency into pq    pq.push(value);  }        pq.sort(function(a,b){return b-a;});       // Traverse the priority_queue  while (pq.length!=0)  {    // Stores topmost    // element of pq    let frequent = pq[0];      // Pop the topmost element    pq.shift();      // If pq is empty    if (pq.length==0) {        // Return cntChar      return cntChar;    }      // If frequent and topmost    // element of pq are equal    if (frequent == pq[0])    {      // If frequency of the topmost      // element is greater than 1      if (frequent > 1)      {        // Insert the decremented        // value of frequent        pq.push(frequent - 1);        pq.sort(function(a,b){return b-a;});      }        // Update cntChar      cntChar++;    }  }    return cntChar;} // Driver Codelet str = "abbbcccd";let N = str.length;document.write(minCntCharDeletionsfrequency(         str.split(""), N));  // This code is contributed by unknown2108</script>
2
 
Time Complexity:O(N) Auxiliary Space:O(256)
mohit kumar 29
Rajput-Ji
shikhasingrajput
unknown2108
cpp-unordered_map
frequency-counting
priority-queue
Greedy
Hash
Queue
Strings
Hash
Strings
Greedy
Queue
priority-queue
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Huffman Coding | Greedy Algo-3
Program for Shortest Job First (or SJF) CPU Scheduling | Set 1 (Non- preemptive)
Fractional Knapsack Problem
Activity Selection Problem | Greedy Algo-1
Job Sequencing Problem
Given an array A[] and a number x, check for pair in A[] with sum as x (aka Two Sum)
Internal Working of HashMap in Java
Hashing | Set 1 (Introduction)
Hashing | Set 3 (Open Addressing)
Hashing | Set 2 (Separate Chaining)