Minimum sum of squares of character counts in a given string after removing k characters
Given a string of lowercase alphabets and a number k, the task is to print the minimum value of the string after removal of ‘k’ characters. The value of a string is defined as the sum of squares of the count of each distinct character.
For example consider the string “saideep”, here frequencies of characters are s-1, a-1, i-1, e-2, d-1, p-1 and value of the string is 1^2 + 1^2 + 1^2 + 1^2 + 1^2 + 2^2 = 9.
Expected Time Complexity: O(k*logn)
Examples:
Input : str = abccc, K = 1
Output : 6
Explanation: We remove c to get the value as 12 + 12 + 22
Input : str = aaab, K = 2
Output : 2
Asked In: Amazon
One clear observation is that we need to remove character with highest frequency. One trick is the character ma
A Simple solution is to use sorting technique through all current highest frequency reduce up to k times. For After every reduce again sort frequency array.
A Better Solution used to Priority Queue which has to the highest element on top.
- Initialize empty priority queue.
- Count frequency of each character and Store into temp array.
- Remove K characters which have highest frequency from queue.
- Finally Count Sum of square of each element and return it.
Below is the implementation of the above idea.
C++
#include <bits/stdc++.h>
using namespace std;
const int MAX_CHAR = 26;
int minStringValue(string str, int k)
{
int l = str.length();
if (k >= l)
return 0;
int frequency[MAX_CHAR] = { 0 };
for ( int i = 0; i < l; i++)
frequency[str[i] - 'a' ]++;
priority_queue< int > q;
for ( int i = 0; i < MAX_CHAR; i++)
q.push(frequency[i]);
while (k--) {
int temp = q.top();
q.pop();
temp = temp - 1;
q.push(temp);
}
int result = 0;
while (!q.empty()) {
int temp = q.top();
result += temp * temp;
q.pop();
}
return result;
}
int main()
{
string str = "abbccc" ;
int k = 2;
cout << minStringValue(str, k) << endl;
str = "aaab" ;
k = 2;
cout << minStringValue(str, k);
return 0;
}
|
Java
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Collections;
public class GFG {
static final int MAX_CHAR = 26 ;
static int minStringValue(String str, int k)
{
int l = str.length();
if (k >= l)
return 0 ;
int [] frequency = new int [MAX_CHAR];
for ( int i = 0 ; i < l; i++)
frequency[str.charAt(i) - 'a' ]++;
PriorityQueue<Integer> q = new PriorityQueue<>(Collections.reverseOrder());
for ( int i = 0 ; i < MAX_CHAR; i++) {
if (frequency[i] != 0 )
q.add(frequency[i]);
}
while (k != 0 ) {
q.add(q.poll() - 1 );
k--;
}
int result = 0 ;
while (!q.isEmpty()) {
result += q.peek() * q.poll();
}
return result;
}
public static void main(String args[])
{
String str = "abbccc" ;
int k = 2 ;
System.out.println(minStringValue(str, k));
str = "aaab" ;
k = 2 ;
System.out.println(minStringValue(str, k));
}
}
|
Python 3
from queue import PriorityQueue
MAX_CHAR = 26
def minStringValue( str , k):
l = len ( str )
if (k > = l):
return 0
frequency = [ 0 ] * MAX_CHAR
for i in range ( 0 , l):
frequency[ ord ( str [i]) - 97 ] + = 1
q = PriorityQueue()
for i in range ( 0 , MAX_CHAR):
q.put( - frequency[i])
while (k > 0 ):
temp = q.get()
temp = temp + 1
q.put(temp, temp)
k = k - 1
result = 0 ;
while not q.empty():
temp = q.get()
temp = temp * ( - 1 )
result + = temp * temp
return result
if __name__ = = "__main__" :
str = "abbccc"
k = 2
print (minStringValue( str , k))
str = "aaab"
k = 2
print (minStringValue( str , k))
|
C#
using System;
using System.Collections.Generic;
class GFG {
static readonly int MAX_CHAR = 26;
static int minStringValue(String str, int k)
{
int l = str.Length;
if (k >= l)
return 0;
int [] frequency = new int [MAX_CHAR];
for ( int i = 0; i < l; i++)
frequency[str[i] - 'a' ]++;
List< int > q = new List< int >();
for ( int i = 0; i < MAX_CHAR; i++)
{
if (frequency[i] != 0)
q.Add(frequency[i]);
}
while (k != 0)
{
q.Sort();
q.Reverse();
q.Add(q[0] - 1);
q.RemoveAt(0);
k--;
}
int result = 0;
while (q.Count != 0)
{
result += q[0] * q[0];
q.RemoveAt(0);
}
return result;
}
public static void Main(String []args)
{
String str = "abbccc" ;
int k = 2;
Console.WriteLine(minStringValue(str, k));
str = "aaab" ;
k = 2;
Console.WriteLine(minStringValue(str, k));
}
}
|
Javascript
<script>
let MAX_CHAR = 26;
function minStringValue(str,k)
{
let l = str.length;
if (k >= l)
return 0;
let frequency = new Array(MAX_CHAR);
for (let i=0;i<MAX_CHAR;i++)
frequency[i]=0;
for (let i = 0; i < l; i++)
frequency[str[i].charCodeAt(0) - 'a' .charCodeAt(0)]++;
let q = [];
for (let i = 0; i < MAX_CHAR; i++) {
if (frequency[i] != 0)
q.push(frequency[i]);
}
q.sort( function (a,b){ return b-a;});
while (k != 0) {
q.push(q.shift() - 1);
q.sort( function (a,b){ return b-a;});
k--;
}
let result = 0;
while (q.length!=0) {
result += q[0] * q.shift();
}
return result;
}
let str = "abbccc" ;
let k = 2;
document.write(minStringValue(str, k)+ "<br>" );
str = "aaab" ;
k = 2;
document.write(minStringValue(str, k)+ "<br>" );
</script>
|
Time Complexity: O(k*logn)
Auxiliary Space: O(N) because constant size array but priority_queue is storing characters almost the length of the string in worst case.
Efficient Approach :
We can solve it in O(N) time complexity as we need to be greedy and always remove the characters of alphabets which are higher in frequency.
Example: Let str=”abbccc” and k=2 now, alphabetCount[1]=1;//for ‘a’ alphabetCount[2]=2;//for ‘b’ alphabetCount[3]=3;//for ‘c’ maximum=3 m[1]=1(only a occur 1 times) m[2]=1(only b occur 2 times) m[3]=1(only c occur 3 times) //k=2 maximum=3 so k=k-m[maximum]//k=k-1; so now one c got removes so frequencies are a=1,b=2,c=2; so as c’s frequency got decreased by one m[maximum] will be zero and m[maximum-1] will be increased by m[maximum] so update m[2]+=m[3], m[3]=0; also maximum gets decreased by one as it is guaranteed to exist frequency one less than maximum from above. m[1]=1 , m[2]=2 , m[3]=0 and k=1; now m[maximum](i.e m[2]=2>k) so we should partially remove remove one character of either b or c so m[1]=2 0,m[2]=1 ,m[3]=0 and k=0; so, (1*1)*2 + (2*2)*1 + (3*3)*0 = 6//ans
Implementation:
C++
#include <bits/stdc++.h>
using namespace std;
const int MAX_CHAR = 26;
int minStringValue(string str, int k)
{
int alphabetCount[MAX_CHAR]= {0};
int m[str.length()] = { 0 };
for ( int i = 0; i < str.length(); i++) {
alphabetCount[str[i] - 'a' ]++;
}
int maximum = 0;
for ( int i = 0; i < MAX_CHAR; i++) {
m[alphabetCount[i]]++;
maximum = max(maximum, alphabetCount[i]);
}
while (k > 0) {
int z = m[maximum];
if (z <= k) {
k = k - z;
m[maximum] = 0;
m[maximum - 1] += z;
maximum--;
}
else {
m[maximum] -= k;
maximum--;
m[maximum] += k;
k = 0;
}
}
int ans = 0;
for ( int i = 0; i < str.length(); i++) {
ans += (i * i) * m[i];
}
return ans;
}
int main()
{
string str = "abbccc" ;
int k = 2;
cout << minStringValue(str, k) << endl;
str = "aaab" ;
k = 2;
cout << minStringValue(str, k);
return 0;
}
|
Java
import java.util.Collections;
import java.util.Comparator;
import java.util.PriorityQueue;
public class GFG {
static final int MAX_CHAR = 26 ;
static int minStringValue(String str, int k)
{
int [] alphabetCount = new int [MAX_CHAR];
int [] m = new int [str.length()];
for ( int i = 0 ; i < str.length(); i++) {
alphabetCount[str.charAt(i) - 'a' ]++;
}
int maximum = 0 ;
for ( int i = 0 ; i < MAX_CHAR; i++) {
m[alphabetCount[i]]++;
maximum = Math.max(maximum, alphabetCount[i]);
}
while (k > 0 ) {
int z = m[maximum];
if (z <= k) {
k = k - z;
m[maximum] = 0 ;
m[maximum - 1 ] += z;
maximum--;
}
else {
m[maximum] -= k;
maximum--;
m[maximum] += k;
k = 0 ;
}
}
int ans = 0 ;
for ( int i = 0 ; i < str.length(); i++) {
ans += (i * i) * m[i];
}
return ans;
}
public static void main(String args[])
{
String str = "abbccc" ;
int k = 2 ;
System.out.println(minStringValue(str, k));
str = "aaab" ;
k = 2 ;
System.out.println(minStringValue(str, k));
}
}
|
Python3
MAX_CHAR = 26
def minStringValue( str , k):
alphabetCount = []
for i in range (MAX_CHAR):
alphabetCount.append( 0 )
m = []
for i in range ( len ( str )):
m.append( 0 )
for i in range ( len ( str )):
alphabetCount[ ord ( str [i]) - ord ( 'a' )] + = 1
maximum = 0
for i in range (MAX_CHAR):
m[alphabetCount[i]] + = 1
maximum = max (maximum, alphabetCount[i])
while (k > 0 ):
z = m[maximum]
if z < = k:
k = k - z
m[maximum] = 0
m[maximum - 1 ] + = z
maximum - = 1
else :
m[maximum] - = k
maximum - = 1
m[maximum] + = k
k = 0
ans = 0
for i in range ( len ( str )):
ans = ans + (i * i) * m[i]
return ans
str = "abbccc"
k = 2
print (minStringValue( str , k))
str = "aaab"
k = 2
print (minStringValue( str , k))
|
C#
using System;
public static class GFG {
static int MAX_CHAR = 26;
static int minStringValue( string str, int k)
{
int [] alphabetCount = new int [MAX_CHAR];
int [] m = new int [str.Length];
for ( int i = 0; i < str.Length; i++) {
alphabetCount[str[i] - 'a' ]++;
}
int maximum = 0;
for ( int i = 0; i < MAX_CHAR; i++) {
m[alphabetCount[i]]++;
maximum = Math.Max(maximum, alphabetCount[i]);
}
while (k > 0) {
int z = m[maximum];
if (z <= k) {
k = k - z;
m[maximum] = 0;
m[maximum - 1] += z;
maximum--;
}
else {
m[maximum] -= k;
maximum--;
m[maximum] += k;
k = 0;
}
}
int ans = 0;
for ( int i = 0; i < str.Length; i++) {
ans += (i * i) * m[i];
}
return ans;
}
public static void Main()
{
string str = "abbccc" ;
int k = 2;
Console.Write(minStringValue(str, k));
Console.Write( "\n" );
str = "aaab" ;
k = 2;
Console.Write(minStringValue(str, k));
}
}
|
Javascript
<script>
let MAX_CHAR = 26;
function minStringValue(str,k)
{
var alphabetCount = new Array(MAX_CHAR).fill(0);
var m = new Array(str.length).fill(0);
var i;
for (i = 0; i < str.length; i++) {
alphabetCount[str.charCodeAt(i) - 97]++;
}
var maximum = 0;
for (i = 0; i < MAX_CHAR; i++) {
m[alphabetCount[i]]++;
maximum = Math.max(maximum, alphabetCount[i]);
}
while (k > 0) {
var z = m[maximum];
if (z <= k) {
k = k - z;
m[maximum] = 0;
m[maximum - 1] += z;
maximum--;
}
else {
m[maximum] -= k;
maximum--;
m[maximum] += k;
k = 0;
}
}
var ans = 0;
for (i = 0; i < str.length; i++) {
ans += (i * i) * m[i];
}
return ans;
}
let str = "abbccc" ;
let k = 2;
document.write(minStringValue(str, k)+ "<br>" );
str = "aaab" ;
k = 2;
document.write(minStringValue(str, k)+ "<br>" );
</script>
|
Time Complexity: O(N)
Space Complexity: O(N)
Last Updated :
30 Apr, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...