Minimum deletions required to make frequency of each letter unique

Given a string S consisting of lowercase characters, you have to delete the minimum number of characters from S so that every letter in S appears a unique number of times.

Examples:

Input: str = “aaaabbbb”
Output: 1
Both ‘a’ and ‘b’ occur 4 times if the first character is deleted then ‘a’ occurs 3 times and ‘b’ occurs 4 times.



Input: str = “geeksforgeeks”
Output: 6

Approach:

  • We can count the frequencies of all 26 possible lower case characters.
  • Then construct a map that tells how many letters have a given frequency.
  • Iterate the map from higher frequencies to lower.
    1. If more than 1 letter has a given frequency we delete 1 occurrence of all but 1 letter with that frequency.
    2. Deleting 1 occurrence of those letters increases the number of the letter that has the frequency one less.
  • If the occurrence of a letter is 0 then it is not present in the string.

Below is the implementation of the above approach:

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ implementation of the
// approach
#include <bits/stdc++.h>
using namespace std;
  
// Returns the mininum number
// of characters to be deleted
// so that all remaining characters
// occur unique number of times.
int minimumDeletions(string s)
{
    // Stores how many times a
    // character occurs. freqOfLetter[0]
    // stores the frequency of letter 'a'
    vector<int> freqOfLetter(26, 0);
  
    for (int i = 0; i < s.length(); i++) {
        freqOfLetter[s[i] - 'a']++;
    }
  
    // Number of characters that
    // have a given frequency
    map<int, int, greater<int> > LetterFreqMap;
  
    for (int i = 0; i < 26; i++) {
  
        // insert the frequency of
        // all lowercase letters in
        // the map that have a
        // frequency greater than 0
        if (freqOfLetter[i] != 0) {
            LetterFreqMap[freqOfLetter[i]]++;
        }
    }
  
    // Stores the number of
    // deletions needed
    int deletions = 0;
  
    // Iterate the map using
    // iterator it
    for (auto it = LetterFreqMap.begin();
         it != LetterFreqMap.end();
         it++) {
  
        // If frequency is 0
        // then all occurrences
        // have been deleted.
        if (it->first == 0)
            break;
  
        // Till more than 1
        // character has a
        // given frequency.
        while (it->second > 1) {
  
            // Delete a character
            // that has conflicting
            // frequency
            deletions++;
  
            // Now 1 less character
            // has the given frequency f
            it->second--;
  
            // But 1 more character
            // has the frequency f - 1
            LetterFreqMap[it->first - 1]++;
        }
    }
  
    return deletions;
}
  
// Driver Code
int main()
{
    string s = "geeksforgeeks";
    cout << minimumDeletions(s);
    return 0;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java implementation of the
// approach
import java.util.*;
import java.lang.*;
import java.io.*;
  
class GFG
{
       
// Returns the mininum number
// of characters to be deleted
// so that all remaining characters
// occur unique number of times.
public static int minimumDeletions(char[] s)
{
    // Stores how many times a
    // character occurs. freqOfLetter[0]
    // stores the frequency of letter 'a'
    int[] freqOfLetter;
    freqOfLetter = new int[26];
  
    for (int i = 0; i < 26; i++)
        freqOfLetter[i] = 0;
  
    for (int i = 0; i < s.length; i++)
    {
        freqOfLetter[s[i] - 'a']++;
    }
  
    // Number of characters that
    // have a given frequency
    Map<Integer,
        Integer > LetterFreqMap = new TreeMap<Integer, 
        Integer >(Collections.reverseOrder());
  
    for (int i = 0; i < 26; i++) 
    {
  
        // insert the frequency of
        // all lowercase letters in
        // the map that have a
        // frequency greater than 0
        if (freqOfLetter[i] != 0)
        {
            if (LetterFreqMap.containsKey(freqOfLetter[i])) 
            {
                LetterFreqMap.put(freqOfLetter[i], 
                LetterFreqMap.get(freqOfLetter[i]) + 1);
            }
            else
                LetterFreqMap.put(freqOfLetter[i], 1);
        }
    }
      
    // Stores the number of
    // deletions needed
    int deletions = 0;
      
    Set<Map.Entry<Integer, 
                  Integer>> set = LetterFreqMap.entrySet();
    for (Map.Entry<Integer, Integer> me : set)
    {
  
        // If frequency is 0
        // then all occurrences
        // have been deleted.
        if (me.getKey() == 0)
            break;
  
        // Till more than 1
        // character has a
        // given frequency.
        while (me.getValue() > 1
        {
  
            // Delete a character
            // that has conflicting
            // frequency
            deletions++;
  
            // Now 1 less character
            // has the given frequency f
            LetterFreqMap.put(me.getKey(), 
            LetterFreqMap.get(me.getKey()) - 1);
  
            // But 1 more character
            // has the frequency f - 1
            if (LetterFreqMap.containsKey(me.getKey() - 1)) 
            {
                LetterFreqMap.put(me.getKey() - 1
                LetterFreqMap.get(me.getKey() - 1) + 1);
            }
            else
                LetterFreqMap.put(me.getKey() - 1, 1);
        }
    }
    return deletions;
}
  
// Driver Code
public static void main(String[] args) throws java.lang.Exception
{
    String s = "geeksforgeeks";
    System.out.println(minimumDeletions(s.toCharArray()));
}
}
  
  
// This code is contributed by ashutosh450 

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python3 implementation of the
# approach
  
# Returns the mininum number
# of characters to be deleted
# so that all remaining characters
# occur unique number of times.
def minimumDeletions(s):
      
    # Stores how many times a
    # character occurs. freqOfLetter[0]
    # stores the frequency of letter 'a'
    freqOfLetter = [0] * 26
  
    for i in range(len(s)):
        freqOfLetter[ord(s[i]) - ord('a')] += 1
  
    # Number of characters that
    # have a given frequency
    LetterFreqMap = dict()
  
    for i in range(26):
  
        # insert the frequency of
        # all lowercase letters in
        # the map that have a
        # frequency greater than 0
        if (freqOfLetter[i] != 0):
            LetterFreqMap[freqOfLetter[i]] = \
            LetterFreqMap.get(freqOfLetter[i], 0) + 1
  
    # Stores the number of deletions needed
    deletions = 0
  
    # Iterate the map using iterator it
    a = list(LetterFreqMap.keys())
    a = a[::-1]
    for it in a:
  
        # If frequency is 0 then all occurrences
        # have been deleted.
        if (it == 0):
            break
  
        # Till more than 1 character has a
        # given frequency.
        x = LetterFreqMap[it]
        while (x > 1):
  
            # Delete a character that has 
            # conflicting frequency
            deletions += 1
  
            # Now 1 less character
            # has the given frequency f
            x -= 1
  
            # But 1 more character
            # has the frequency f - 1
            if (it - 1) in LetterFreqMap.keys():
                LetterFreqMap[it - 1] += 1
  
    return deletions
  
# Driver Code
s = "geeksforgeeks"
print(minimumDeletions(s))
  
# This code is contributed by Mohit Kumar

chevron_right


Output:

6

Time Complexity: O(n + m*m), where m = 26.

  • Counting the frequency of all characters takes O(N) time where N is the length of S.
  • Constructing the map works in O(mlogm) time, where m = 26.
  • Deletion works in O(m*m)


My Personal Notes arrow_drop_up

Final year BTech IT student at DTU, Upcoming Technology Analyst at Morgan Stanley

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.