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:
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int minCntCharDeletionsfrequency(string& str,
int N)
{
unordered_map< char , int > mp;
priority_queue< int > pq;
int cntChar = 0;
for ( int i = 0; i < N; i++) {
mp[str[i]]++;
}
for ( auto it : mp) {
pq.push(it.second);
}
while (!pq.empty()) {
int frequent
= pq.top();
pq.pop();
if (pq.empty()) {
return cntChar;
}
if (frequent == pq.top()) {
if (frequent > 1) {
pq.push(frequent - 1);
}
cntChar++;
}
}
return cntChar;
}
int main()
{
string str = "abbbcccd" ;
int N = str.length();
cout << minCntCharDeletionsfrequency(
str, N);
return 0;
}
|
Java
import java.util.*;
class GFG{
static int minCntCharDeletionsfrequency( char [] str,
int N)
{
HashMap<Character,
Integer> mp =
new HashMap<>();
PriorityQueue<Integer> pq =
new PriorityQueue<>((x, y) ->
Integer.compare(y, x));
int cntChar = 0 ;
for ( int i = 0 ; i < N; i++)
{
if (mp.containsKey(str[i]))
{
mp.put(str[i],
mp.get(str[i]) + 1 );
}
else
{
mp.put(str[i], 1 );
}
}
for (Map.Entry<Character,
Integer> it :
mp.entrySet())
{
pq.add(it.getValue());
}
while (!pq.isEmpty())
{
int frequent = pq.peek();
pq.remove();
if (pq.isEmpty()) {
return cntChar;
}
if (frequent == pq.peek())
{
if (frequent > 1 )
{
pq.add(frequent - 1 );
}
cntChar++;
}
}
return cntChar;
}
public static void main(String[] args)
{
String str = "abbbcccd" ;
int N = str.length();
System.out.print(minCntCharDeletionsfrequency(
str.toCharArray(), N));
}
}
|
Python3
def minCntCharDeletionsfrequency( str , N):
mp = {}
pq = []
cntChar = 0
for i in range (N):
mp[ str [i]] = mp.get( str [i], 0 ) + 1
for it in mp:
pq.append(mp[it])
pq = sorted (pq)
while ( len (pq) > 0 ):
frequent = pq[ - 1 ]
del pq[ - 1 ]
if ( len (pq) = = 0 ):
return cntChar
if (frequent = = pq[ - 1 ]):
if (frequent > 1 ):
pq.append(frequent - 1 )
cntChar + = 1
pq = sorted (pq)
return cntChar
if __name__ = = '__main__' :
str = "abbbcccd"
N = len ( str )
print (minCntCharDeletionsfrequency( str , N))
|
C#
using System;
using System.Collections.Generic;
class GFG{
static int minCntCharDeletionsfrequency( char [] str,
int N)
{
Dictionary< char ,
int > mp = new Dictionary< char ,
int >();
List< int > pq = new List< int >();
int cntChar = 0;
for ( int i = 0; i < N; i++)
{
if (mp.ContainsKey(str[i]))
{
mp[str[i]]++;
}
else
{
mp.Add(str[i], 1);
}
}
foreach (KeyValuePair< char , int > it in mp)
{
pq.Add(it.Value);
}
pq.Sort();
pq.Reverse();
while (pq.Count != 0)
{
pq.Sort();
pq.Reverse();
int frequent = pq[0];
pq.RemoveAt(0);
if (pq.Count == 0)
{
return cntChar;
}
if (frequent == pq[0])
{
if (frequent > 1)
{
pq.Add(frequent - 1);
pq.Sort();
}
cntChar++;
}
}
return cntChar;
}
public static void Main(String[] args)
{
String str = "abbbcccd" ;
int N = str.Length;
Console.Write(minCntCharDeletionsfrequency(
str.ToCharArray(), N));
}
}
|
Javascript
<script>
function minCntCharDeletionsfrequency(str,N)
{
let mp = new Map();
let pq =[];
let cntChar = 0;
for (let i = 0; i < N; i++)
{
if (mp.has(str[i]))
{
mp.set(str[i],
mp.get(str[i]) + 1);
}
else
{
mp.set(str[i], 1);
}
}
for (let [key, value] of mp.entries())
{
pq.push(value);
}
pq.sort( function (a,b){ return b-a;});
while (pq.length!=0)
{
let frequent = pq[0];
pq.shift();
if (pq.length==0) {
return cntChar;
}
if (frequent == pq[0])
{
if (frequent > 1)
{
pq.push(frequent - 1);
pq.sort( function (a,b){ return b-a;});
}
cntChar++;
}
}
return cntChar;
}
let str = "abbbcccd" ;
let N = str.length;
document.write(minCntCharDeletionsfrequency(
str.split( "" ), N));
</script>
|
Time Complexity:O(N)
Auxiliary Space:O(1)
Approach 2: Decrement each duplicate until it is unique
we will first start by calculating the frequency of each character. Then, in this approach, we will iterate over the frequencies, and for each frequency, we will check to see if this frequency has already been seen. If it has, we will decrease the frequency until it becomes unique or zero (signifying that we have deleted all occurrences of this character).
- Store the frequency for each character in the given string s in a frequency array called fre (of size 26 for each character). We store the frequency of each character c at index c-‘a’.
- initialize the cnt to 0 , which stores the count of characters that need to be deleted. Also, initialize a HashSet seen that stores the frequencies that we have occupied.
- Iterate over the characters from a to z as 0 to 25, for each character:
1. keep decrementing the frequency of character until it is not present in seen and increment the cnt each time we decrement frequency.
2. when the frequency becomes unique (or zero) insert it into the set seen.
C++
#include <bits/stdc++.h>
using namespace std;
int minDeletions(string s)
{
vector< int > fre(26, 0);
set< int > seen;
int cnt = 0;
for ( int i = 0; i < s.length(); i++) {
fre[s[i] - 'a' ]++;
}
for ( int i = 0; i < 26; i++) {
while (fre[i] && seen.find(fre[i]) != seen.end()) {
fre[i]--;
cnt++;
}
seen.insert(
fre[i]);
}
return cnt;
}
int main()
{
string s = "abbbcccd" ;
cout << minDeletions(s) << endl;
return 0;
}
|
Java
import java.util.*;
class GFG{
static int minCntCharDeletionsfrequency( char [] str,
int N)
{
HashMap<Character, Integer> map = new HashMap<Character, Integer>();
int count = 0 ;
for ( char c: str){
if (!map.containsKey(c)){
map.put(c, 1 );
} else {
map.put(c, map.get(c) + 1 );
}
}
ArrayList<Integer> frequencies = new ArrayList<>(map.values());
HashSet<Integer> set = new HashSet<Integer>();
for ( int value: frequencies){
if (!set.contains(value)){
set.add(value);
} else {
while (value > 0 && set.contains(value)){
value--;
count++;
}
set.add(value);
}
}
return count;
}
public static void main(String[] args)
{
String str = "abbbcccd" ;
int N = str.length();
System.out.print(minCntCharDeletionsfrequency(
str.toCharArray(), N));
}
}
|
Python3
def minCntCharDeletionsfrequency(s ,n) - > int :
legend = {}
freq = [ False for i in range (n + 1 )]
for c in s:
if c not in legend:
legend = 1
else :
legend + = 1
res = 0
for key, val in legend.items():
while freq[val] and val > 0 :
val - = 1
res + = 1
freq[val] = True
return res
if __name__ = = '__main__' :
str = "abbbcccd"
N = len ( str )
print (minCntCharDeletionsfrequency( str , N))
|
C#
using System;
using System.Collections.Generic;
class GFG {
static int minCntCharDeletionsfrequency( char [] str,
int N)
{
Dictionary< char , int > map
= new Dictionary< char , int >();
int count = 0;
foreach ( char c in str)
{
if (!map.ContainsKey(c)) {
map.Add(c, 1);
}
else {
map++;
}
}
List< int > frequencies = new List< int >(map.Values);
HashSet< int > set = new HashSet< int >();
foreach ( int value in frequencies)
{
if (! set .Contains(value)) {
set .Add(value);
}
else {
int tempValue = value;
while (tempValue > 0
&& set .Contains(tempValue)) {
tempValue--;
count++;
}
set .Add(tempValue);
}
}
return count;
}
public static void Main( string [] args)
{
string str = "abbbcccd" ;
int N = str.Length;
Console.Write(minCntCharDeletionsfrequency(
str.ToCharArray(), N));
}
}
|
Javascript
function minDeletions(s) {
let fre = Array(26).fill(0);
let seen = new Set();
let cnt = 0;
for (let i = 0; i < s.length; i++) {
fre[s.charCodeAt(i) - 'a' .charCodeAt(0)]++;
}
for (let i = 0; i < 26; i++) {
while (fre[i] && seen.has(fre[i])) {
fre[i]--;
cnt++;
}
seen.add(fre[i]);
}
return cnt;
}
let s = "abbbcccd" ;
console.log(minDeletions(s));
|
Output
2
Time Complexity: O(N)
Auxiliary Space: O(N)