Open In App

Remove k characters in a String such that ASCII sum is minimum

Last Updated : 08 Feb, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

Given a string s and an integer k, the task is to remove k characters from the string such that the sum of ASCII (American Standard Code for Information Interchange) values of the remaining characters is minimized.

Examples:

Input: s = “ABbc”, k = 2
Output: 131
Explanation: We need to remove exactly 2 characters from the string “ABbc” to minimize the ASCII sum of the remaining characters. By removing ‘b’ and ‘c’, we obtain the minimum sum of 131, which corresponds to the ASCII sum of the remaining characters (‘A’ and ‘B’).

Input: s = “abaacd”, k = 3
Output: 291
Explanation: We need to remove exactly 3 characters from the string “abaacd” to minimize the ASCII sum of the remaining characters. By removing ‘b’, ‘c’, and ‘d’, we obtain the minimum sum of 297, which corresponds to the ASCII sum of the remaining characters (‘a’, ‘a’, and ‘a’).

Approach: To solve the problem follow the below idea:

To solve this problem, we can use a Greedy approach. The idea is to sort the characters of the given string in ascending order of their ASCII values, and then remove k characters from the end of the sorted string. This approach ensures that we are removing characters with the highest ASCII values, which will result in the minimum sum of the remaining characters.

Here are the steps of the approach:

  • Create an array to store the frequency of each character in the string s.
  • Sort the characters of the string s in ascending order of their ASCII values.
  • Traverse the sorted string s, and for each character, decrement its frequency in the frequency array.
  • While traversing the sorted string s, keep track of the number of characters removed so far.
    • If the current character has a frequency greater than k, then remove k characters from the end of the sorted string s, and break the loop.
    • Otherwise, remove all the characters of the current character from the end of the sorted string s, and subtract its ASCII value multiplied by its frequency from the sum of the remaining characters.
    • If k characters have been removed, then break the loop.
  • If the loop completes without breaking, then remove the remaining k characters from the end of the sorted string s, and subtract their ASCII values from the sum of the remaining characters.
  • Return the sum of the remaining characters.

Below is the implementation of the above approach:

C++




// C++ code for the above approach:
#include <bits/stdc++.h>
using namespace std;
 
int minAsciiSum(string s, int k)
{
    int freq[26] = { 0 };
    for (int i = 0; i < s.length(); i++) {
        freq[s[i] - 'a']++;
    }
    sort(s.begin(), s.end());
    int sum = 0, removed = 0;
    for (int i = 0; i < s.length(); i++) {
        int ch = s[i] - 'a';
        if (freq[ch] > k - removed) {
            sum += (k - removed) * (s[i]);
            removed = k;
            break;
        }
        else {
            sum += freq[ch] * (s[i]);
            removed += freq[ch];
            freq[ch] = 0;
        }
        if (removed == k) {
            break;
        }
    }
    if (removed < k) {
        sum += (k - removed) * (s[s.length() - 1]);
    }
    return sum;
}
 
// Drivers code
int main()
{
    string s = "abaacd";
    int k = 3;
 
    // Function Call
    cout << minAsciiSum(s, k) << endl;
    return 0;
}


Java




// Java code for the above approach:
import java.util.*;
 
class GFG {
    static int minAsciiSum(String s, int k)
    {
        int freq[] = new int[26];
        for (int i = 0; i < s.length(); i++) {
            freq[s.charAt(i) - 'a']++;
        }
        char[] ch = s.toCharArray();
        Arrays.sort(ch);
        s = new String(ch);
        int sum = 0, removed = 0;
        for (int i = 0; i < s.length(); i++) {
            int ch1 = s.charAt(i) - 'a';
            if (freq[ch1] > k - removed) {
                sum += (k - removed) * (s.charAt(i));
                removed = k;
                break;
            }
            else {
                sum += freq[ch1] * (s.charAt(i));
                removed += freq[ch1];
                freq[ch1] = 0;
            }
            if (removed == k) {
                break;
            }
        }
        if (removed < k) {
            sum += (k - removed)
                   * (s.charAt(s.length() - 1));
        }
        return sum;
    }
 
    // Driver code
    public static void main(String[] args)
    {
        String s = "abaacd";
        int k = 3;
 
        // Function Call
        System.out.println(minAsciiSum(s, k));
    }
}
// This code is contributed by Tapesh(tapeshdua420)


Python3




# python code for the above approach:
 
def minAsciiSum(s, k):
    freq = [0] * 26
    for ch in s:
        freq[ord(ch) - ord('a')] += 1
    s = sorted(s)
    sum = 0
    removed = 0
    for ch in s:
        idx = ord(ch) - ord('a')
        if freq[idx] > k - removed:
            sum += (k - removed) * ord(ch)
            removed = k
            break
        else:
            sum += freq[idx] * ord(ch)
            removed += freq[idx]
            freq[idx] = 0
        if removed == k:
            break
    if removed < k:
        sum += (k - removed) * ord(s[-1])
    return sum
 
# Driver Code
if __name__ == '__main__':
    s = "abaacd"
    k = 3
    # Function Call
    print(minAsciiSum(s, k))


C#




//  C# code for the above approach:
using System;
using System.Linq;
 
class GFG
{
    static int MinAsciiSum(string s, int k)
    {
        int[] freq = new int[26];
 
        // Calculate the frequency of each character in the
       // input string 's'
        foreach (char c in s)
        {
            freq++;
        }
 
        // Sort the string in ascending order
        char[] sortedS = s.OrderBy(c => c).ToArray();
 
        int sum = 0, removed = 0;
 
        // Loop through the sorted string 'sortedS'
        for (int i = 0; i < sortedS.Length; i++)
        {
            char ch = sortedS[i];
            int charIndex = ch - 'a';
 
            // Check if the frequency of the current character
           // is greater than 'k - removed'
            if (freq[charIndex] > k - removed)
            {
                // Add the sum of ASCII values of (k - removed)
               // instances of the character 'ch' to 'sum'
                sum += (k - removed) * ch;
                removed = k;
                break;
            }
            else
            {
                // Add the sum of ASCII values of all instances of
               // the character 'ch' to 'sum'
                sum += freq[charIndex] * ch;
                // Update 'removed' by adding the frequency of
               // the current character to it
                removed += freq[charIndex];
                // Set the frequency of the character to zero to
               // mark it as "removed"
                freq[charIndex] = 0;
            }
 
            // Check if we have removed 'k' characters,
          // break out of the loop
            if (removed == k)
            {
                break;
            }
        }
 
        // If 'removed' is still less than 'k', add the sum
       // of ASCII values of (k - removed) instances of the last
      // character in the sorted string
        if (removed < k)
        {
            char lastChar = sortedS[sortedS.Length - 1];
            sum += (k - removed) * lastChar;
        }
 
        return sum;
    }
//Driver code
    static void Main()
    {
        string s = "abaacd";
        int k = 3;
 
        // Function Call
        Console.WriteLine(MinAsciiSum(s, k));
    }
}


Javascript




// JavaScript code for the above approach:
 
function minAsciiSum(s, k) {
  let freq = new Array(26).fill(0);
  for (let ch of s) {
    freq[ch.charCodeAt(0) - 'a'.charCodeAt(0)] += 1;
  }
  s = s.split('').sort().join('');
  let sum = 0;
  let removed = 0;
  for (let ch of s) {
    let idx = ch.charCodeAt(0) - 'a'.charCodeAt(0);
    if (freq[idx] > k - removed) {
      sum += (k - removed) * ch.charCodeAt(0);
      removed = k;
      break;
    } else {
      sum += freq[idx] * ch.charCodeAt(0);
      removed += freq[idx];
      freq[idx] = 0;
    }
    if (removed === k) {
      break;
    }
  }
  if (removed < k) {
    sum += (k - removed) * s.charCodeAt(s.length - 1);
  }
  return sum;
}
 
// Driver Code
let s = "abaacd";
let k = 3;
// Function Call
console.log(minAsciiSum(s, k));
 
// This code is contributed by Tapesh(tapeshdua420)


Output

291

Time Complexity: O(n*logn), where n is the length of the string.
Auxiliary Space: O(1), because we are using a fixed-size array of size 26 to store the frequency of each character in the string.



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads