Maximum non-repeating characters after removing K characters

Given a string S containing lowercase English alphabets of length N and an integer K such that K ≤ N. The task is to find the maximum number of non-repeating characters after removing K characters from the string.

Examples:

Input: S = “geeksforgeeks”, K = 3
Output: 6
Explanation:
Remove 1 occurrences of each g, k and s so the final string is “geeksforee” and the 6 distinct elements are g, k, s, f, o and r

Input: S = “aabbccddeeffgghh”, k = 1
Output: 1
Explanation:
Remove 1 occurrences of any character we will have only one character which will non repeating.

Naive Approach: The naive idea is to delete all possible K characters among the given string and then find the non-repeating characters in all the formed string. Print the maximum among all the count of non-repeating characters.
Time Complexity: O(N!), where N is the length of the given string.
Auxiliary Space: O(N-K)

Efficient Approach: To optimize the above approach,  



The idea is to delete K characters in increasing order of frequency whose frequency is at least 2 to get the count of maximum non-repeating characters. 
 

Below are the steps: 

  1. Create a hash table to store the frequency of each element.
  2. Insert the frequency of each element in a vector V and sort the vector V in increasing order.
  3. For each element(say currentElement) of vector V find the minimum among K and currentElement – 1 and decrease both K and V[i] by the minimum of the two.
  4. Repeat the above step until K is non-zero.
  5. The count of 1s in vector V gives the maximum number of non-repeating characters after deleting K characters.

 Below is the implementation of the above approach:

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ program for the above approach
  
#include <bits/stdc++.h>
using namespace std;
  
// Function to find maximum distinct
// character after removing K character
int maxDistinctChar(string s, int n, int k)
{
    // Freq implemented as hash table to
    // store frequency of each character
    unordered_map<int, int> freq;
  
    // Store frequency of each character
    for (int i = 0; i < n; i++)
        freq[s[i]]++;
  
    vector<int> v;
  
    // Insert each frequency in v
    for (auto it = freq.begin();
         it != freq.end(); it++) {
        v.push_back(it->second);
    }
  
    // Sort the freq of character in
    // non-decresing order
    sort(v.begin(), v.end());
  
    // Traverse the vector
    for (int i = 0; i < v.size(); i++) {
        int mn = min(v[i] - 1, k);
  
        // Update v[i] and k
        v[i] -= mn;
        k -= mn;
    }
  
    // If K is still not 0
    if (k > 0) {
  
        for (int i = 0; i < v.size(); i++) {
            int mn = min(v[i], k);
            v[i] -= mn;
            k -= mn;
        }
    }
  
    // Store the final answer
    int res = 0;
    for (int i = 0; i < v.size(); i++)
  
        // Count this character if freq 1
        if (v[i] == 1)
            res++;
  
    // Return count of distinct characters
    return res;
}
  
// Driver Code
int main()
{
    // Given string
    string S = "geeksforgeeks";
  
    int N = S.size();
  
    // Given k
    int K = 1;
  
    // Function Call
    cout << maxDistinctChar(S, N, K);
  
    return 0;
}
chevron_right

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java program for the above approach
import java.util.*;
class GFG{
  
// Function to find maximum distinct
// character after removing K character
static int maxDistinctChar(char []s, int n, int k)
{
    // Freq implemented as hash table to
    // store frequency of each character
    HashMap<Integer,
            Integer> freq  = new HashMap<Integer,
                                         Integer>();
  
    // Store frequency of each character
    for (int i = 0; i < n; i++) 
    {
        if(freq.containsKey((int)s[i]))
        {
            freq.put((int)s[i], 
                     freq.get((int)s[i]) + 1);
        }
        else
        {
            freq.put((int)s[i], 1);
        }
    }
  
    Vector<Integer> v = new Vector<Integer>();
  
    // Insert each frequency in v
    for (Map.Entry<Integer, Integer> it : freq.entrySet()) 
    {
        v.add(it.getValue());
    }
  
    // Sort the freq of character in
    // non-decresing order
    Collections.sort(v);
  
    // Traverse the vector
    for (int i = 0; i < v.size(); i++) 
    {
        int mn = Math.min(v.get(i) - 1, k);
  
        // Update v[i] and k
        v.set(i, v.get(i) - mn);
        k -= mn;
    }
  
    // If K is still not 0
    if (k > 0
    {
        for (int i = 0; i < v.size(); i++) 
        {
            int mn = Math.min(v.get(i), k);
            v.set(i, v.get(i) - mn);
            k -= mn;
        }
    }
  
    // Store the final answer
    int res = 0;
    for (int i = 0; i < v.size(); i++)
  
        // Count this character if freq 1
        if (v.get(i) == 1)
            res++;
  
    // Return count of distinct characters
    return res;
}
  
// Driver Code
public static void main(String[] args)
{
    // Given String
    String S = "geeksforgeeks";
  
    int N = S.length();
  
    // Given k
    int K = 1;
  
    // Function Call
    System.out.print(maxDistinctChar(S.toCharArray(), 
                                     N, K));
}
}
  
// This code is contributed by shikhasingrajput
chevron_right

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python3 program for the above approach
from collections import defaultdict
  
# Function to find maximum distinct
# character after removing K character
def maxDistinctChar(s, n, k):
  
    # Freq implemented as hash table to
    # store frequency of each character
    freq = defaultdict (int)
  
    # Store frequency of each character
    for i in range (n):
        freq[s[i]] += 1
  
    v = []
  
    # Insert each frequency in v
    for it in freq.values():
        v.append(it)
  
    # Sort the freq of character in
    # non-decresing order
    v.sort()
  
    # Traverse the vector
    for i in range (len(v)):
        mn = min(v[i] - 1, k)
  
        # Update v[i] and k
        v[i] -= mn
        k -= mn
  
    # If K is still not 0
    if (k > 0):
        for i in range (len(v)):
            mn = min(v[i], k);
            v[i] -= mn
            k -= mn
  
    # Store the final answer
    res = 0
    for i in range (len(v)):
  
        # Count this character if freq 1
        if (v[i] == 1):
            res += 1
  
    # Return count of distinct characters
    return res
  
# Driver Code
if __name__ == "__main__":
    
    # Given string
    S = "geeksforgeeks"
  
    N = len(S)
  
    # Given k
    K = 1
  
    # Function Call
    print(maxDistinctChar(S, N, K))
  
# This code is contributed by Chitranayal
chevron_right

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# program for the above approach
using System;
using System.Collections.Generic;
  
class GFG{
  
// Function to find maximum distinct
// character after removing K character
static int maxDistinctChar(char []s, int n, int k)
{
      
    // Freq implemented as hash table to
    // store frequency of each character
    Dictionary<int,
               int> freq = new Dictionary<int,
                                          int>();
  
    // Store frequency of each character
    for(int i = 0; i < n; i++) 
    {
        if(freq.ContainsKey((int)s[i]))
        {
            freq[(int)s[i]] = freq[(int)s[i]] + 1;
        }
        else
        {
            freq.Add((int)s[i], 1);
        }
    }
  
    List<int> v = new List<int>();
  
    // Insert each frequency in v
    foreach(KeyValuePair<int, int> it in freq) 
    {
        v.Add(it.Value);
    }
  
    // Sort the freq of character in
    // non-decresing order
    v.Sort();
  
    // Traverse the vector
    for(int i = 0; i < v.Count; i++) 
    {
        int mn = Math.Min(v[i] - 1, k);
  
        // Update v[i] and k
        v[i] = v[i] - mn;
        k -= mn;
    }
  
    // If K is still not 0
    if (k > 0) 
    {
        for(int i = 0; i < v.Count; i++) 
        {
            int mn = Math.Min(v[i], k);
            v[i] = v[i] - mn;
            k -= mn;
        }
    }
  
    // Store the readonly answer
    int res = 0;
    for(int i = 0; i < v.Count; i++)
  
        // Count this character if freq 1
        if (v[i] == 1)
            res++;
  
    // Return count of distinct characters
    return res;
}
  
// Driver Code
public static void Main(String[] args)
{
      
    // Given String
    String S = "geeksforgeeks";
  
    int N = S.Length;
  
    // Given k
    int K = 1;
  
    // Function call
    Console.Write(maxDistinctChar(S.ToCharArray(), 
                                  N, K));
}
}
  
// This code is contributed by Amit Katiyar
chevron_right

Output: 
4

Time Complexity: O(N)
Auxiliary Space: O(26)

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.



Article Tags :
Practice Tags :