Given a string S of length N, the task is to find the minimum operations required to make the frequency of every distinct character prime. The frequency of a character can be increased or decreased by 1 in a single operation.
Examples:
Input: S = “abba”
Output: 0
Explanation: There are two characters in the string S and the frequency of ‘a’ is 2 which is prime. The frequency of ‘b’ is 2 which is also a prime number.Hence no operations are required for this case.Input: S = “aaaaaaaaa”
Output: 2
Explanation: The frequency of ‘a’ in the string is 9. Either remove 2 a’s from the string or add 2 a’s in the string to make the frequency of ‘a’ prime. Thus, the minimum number of operations needed is 2.
Naive Approach:
Find the frequency of each character in the string. Let the frequency be X. Find the prime number greater than X and less than X. Compare the difference between X and the two prime numbers found and choose the closest prime number. Add the difference between the closest prime number and X to the number of operations. Thus, the minimum number of operations will be obtained. It is an inefficient approach as the lower and upper bounds to find the prime number are not known.
Efficient Approach:
- Use the sieve algorithm to find all the prime numbers up to N and store them in an array.
- Find out the nearest lower prime number for all the numbers from i = 1 to N and store the difference between i and its nearest lower prime number in an array, say arr1[].
- Find out the nearest higher prime number for all the numbers from i = 1 to N and store the difference between i and its nearest higher prime number in an array, say arr2[].
- Traverse the string and find the frequency of all the distinct characters in the string and use an unordered_map to save the frequencies of these distinct characters.
- Let the frequency of any distinct character be X, then find out the distance between X and the nearest prime number from the arrays arr1[] and arr2[].
- Choose the distance which is less between the two and add this distance to the number of operations.
- Do this for all the distinct characters and print the number of operations finally.
Below is the implementation of the above approach:
C++
// C++ code for the above approach #include <iostream> #include <unordered_map> #include <vector> using namespace std; // using the sieve to find // the prime factors. void spf_array( int spf[], int d) { spf[1] = 1; int i = 0; // setting every number // as prime number initially for (i = 2; i <= d; i++) { spf[i] = i; } // removing the even numbers as // they cannot be prime except 2 for (i = 2; i <= d; i = i + 2) { spf[i] = 2; } for (i = 3; i * i <= d; i++) { // if they are prime if (spf[i] == i) { int j; // iterating the loop for // prime and eliminate all // the multiples of three for (j = i * i; j <= d; j = j + i) { if (spf[j] == j) { spf[j] = i; } } } } } // function to find the closest // prime number of every // number upto N (size of the string) void closest_prime_spf( int spf[], int cspf[], int d) { // for the base case cspf[1] = 1; int i = 0, j = 0, k = 0; // iterating to find the // distance from the // lesser nearest prime for (i = 2; i < d; i++) { if (spf[i] != i) { cspf[i] = abs (i - k); } else { cspf[i] = -1; k = i; } } // iterating to find the // distance from the // lesser nearest prime for (i = d - 1; i >= 2; i--) { if (spf[i] != i) { if (cspf[i] > abs (k - i)) { cspf[i] = abs (k - i); } } else { k = i; } } } // function to find the // minimum operation int minimum_operation( int cspf[], string s) { // created map to find the // frequency of distinct characters unordered_map< char , int > m; // variable to iterate and // holding the minimum operation int i = 0, k = 0; // loop for calculation frequency for (i = 0; i < s.length(); i++) { m[s[i]] = m[s[i]] + 1; } // iterate over frequency // if we not get a character // frequency prime // then we find the closest // prime and add for ( auto x : m) { int h = x.second; if (cspf[h] != -1) { k = k + cspf[h]; } } return k; } // Function to find the // minimum number of operations void minOper(string s) { int spf[s.length() + 1]; int cspf[s.length() + 1]; // function called to create // the spf spf_array(spf, s.length() + 1); // function called to // create the cspf closest_prime_spf(spf, cspf, s.length() + 1); cout << minimum_operation(cspf, s) << endl; } // Driver Code int main() { // input string string s = "aaaaaaaaabbcccccc" ; minOper(s); return 0; } |
Java
// Java code for the above approach import java.util.*; class GFG{ // Using the sieve to find // the prime factors. static void spf_array( int spf[], int d) { spf[ 1 ] = 1 ; int i = 0 ; // Setting every number // as prime number initially for (i = 2 ; i < d; i++) { spf[i] = i; } // Removing the even numbers as // they cannot be prime except 2 for (i = 2 ; i < d; i = i + 2 ) { spf[i] = 2 ; } for (i = 3 ; i * i <= d; i++) { // If they are prime if (spf[i] == i) { int j; // Iterating the loop for // prime and eliminate all // the multiples of three for (j = i * i; j < d; j = j + i) { if (spf[j] == j) { spf[j] = i; } } } } } // Function to find the closest // prime number of every // number upto N (size of the String) static void closest_prime_spf( int spf[], int cspf[], int d) { // For the base case cspf[ 1 ] = 1 ; int i = 0 , k = 0 ; // Iterating to find the // distance from the // lesser nearest prime for (i = 2 ; i < d; i++) { if (spf[i] != i) { cspf[i] = Math.abs(i - k); } else { cspf[i] = - 1 ; k = i; } } // Iterating to find the // distance from the // lesser nearest prime for (i = d - 1 ; i >= 2 ; i--) { if (spf[i] != i) { if (cspf[i] > Math.abs(k - i)) { cspf[i] = Math.abs(k - i); } } else { k = i; } } } // Function to find the // minimum operation static int minimum_operation( int cspf[], String s) { // Created map to find the // frequency of distinct characters HashMap<Character, Integer> m = new HashMap<>(); // Variable to iterate and // holding the minimum operation int i = 0 , k = 0 ; // Loop for calculation frequency for (i = 0 ; i < s.length(); i++) { if (m.containsKey(s.charAt(i))) m.put(s.charAt(i), m.get(s.charAt(i)) + 1 ); else m.put(s.charAt(i), 1 ); } // Iterate over frequency // if we not get a character // frequency prime then we // find the closest // prime and add for (Map.Entry<Character, Integer> x : m.entrySet()) { int h = x.getValue(); if (cspf[h] != - 1 ) { k = k + cspf[h]; } } return k; } // Function to find the // minimum number of operations static void minOper(String s) { int []spf = new int [s.length() + 1 ]; int []cspf = new int [s.length() + 1 ]; // Function called to create // the spf spf_array(spf, s.length() + 1 ); // Function called to // create the cspf closest_prime_spf(spf, cspf, s.length() + 1 ); System.out.print(minimum_operation(cspf, s) + "\n" ); } // Driver Code public static void main(String[] args) { // Input String String s = "aaaaaaaaabbcccccc" ; minOper(s); } } // This code is contributed by Amit Katiyar |
Python3
# Python3 code for the above approach from collections import defaultdict # Using the sieve to find # the prime factors. def spf_array(spf, d): spf[ 1 ] = 1 i = 0 # Setting every number as prime # number initially and remove # even numbers as 2 as they # cannot be prime except 2 for i in range ( 2 , d + 1 ): if (i % 2 = = 0 ): spf[i] = 2 else : spf[i] = i i = 3 while i * i < = d: # If they are prime if (spf[i] = = i): # Iterating the loop for # prime and eliminate all # the multiples of three j = i * i while j < d + 1 : if (spf[j] = = j): spf[j] = i j = j + i i + = 1 # Function to find the closest # prime number of every number # upto N (size of the string) def closest_prime_spf(spf, cspf, d): # For the base case cspf[ 1 ] = 1 i = 0 j = 0 k = 0 # Iterating to find the # distance from the # lesser nearest prime for i in range ( 2 , d): if (spf[i] ! = i): cspf[i] = abs (i - k) else : cspf[i] = - 1 k = i # Iterating to find the # distance from the # lesser nearest prime for i in range (d - 1 , 1 , - 1 ): if (spf[i] ! = i): if (cspf[i] > abs (k - i)): cspf[i] = abs (k - i) else : k = i # Function to find the # minimum operation def minimum_operation(cspf, s): # Created map to find the # frequency of distinct characters m = defaultdict( int ) # Variable to iterate and # holding the minimum operation i = 0 k = 0 # Loop for calculation frequency for i in range ( len (s)): m[s[i]] = m[s[i]] + 1 # Iterate over frequency if we # not get a character frequency # prime then we find the closest # prime and add #print (cspf) for x in m.values(): h = x if (cspf[h] ! = - 1 ): k = k + cspf[h] return k # Function to find the # minimum number of operations def minOper(s): spf = [ 0 ] * ( len (s) + 2 ) cspf = [ 0 ] * ( len (s) + 2 ) # Function called to create # the spf spf_array(spf, len (s) + 1 ) # Function called to # create the cspf closest_prime_spf(spf, cspf, len (s) + 1 ) print (minimum_operation(cspf, s)) # Driver Code if __name__ = = "__main__" : # Input string s = "aaaaaaaaabbcccccc" minOper(s) # This code is contributed by chitranayal |
C#
// C# code for the // above approach using System; using System.Collections.Generic; class GFG{ // Using the sieve to find // the prime factors. static void spf_array( int []spf, int d) { spf[1] = 1; int i = 0; // Setting every number // as prime number initially for (i = 2; i < d; i++) { spf[i] = i; } // Removing the even numbers as // they cannot be prime except 2 for (i = 2; i < d; i = i + 2) { spf[i] = 2; } for (i = 3; i * i <= d; i++) { // If they are prime if (spf[i] == i) { int j; // Iterating the loop for // prime and eliminate all // the multiples of three for (j = i * i; j < d; j = j + i) { if (spf[j] == j) { spf[j] = i; } } } } } // Function to find the closest // prime number of every // number upto N (size of the String) static void closest_prime_spf( int []spf, int []cspf, int d) { // For the base case cspf[1] = 1; int i = 0, k = 0; // Iterating to find the // distance from the // lesser nearest prime for (i = 2; i < d; i++) { if (spf[i] != i) { cspf[i] = Math.Abs(i - k); } else { cspf[i] = -1; k = i; } } // Iterating to find the // distance from the // lesser nearest prime for (i = d - 1; i >= 2; i--) { if (spf[i] != i) { if (cspf[i] > Math.Abs(k - i)) { cspf[i] = Math.Abs(k - i); } } else { k = i; } } } // Function to find the // minimum operation static int minimum_operation( int []cspf, String s) { // Created map to find the // frequency of distinct characters Dictionary< char , int > m = new Dictionary< char , int >(); // Variable to iterate and // holding the minimum operation int i = 0, k = 0; // Loop for calculation // frequency for (i = 0; i < s.Length; i++) { if (m.ContainsKey(s[i])) m[s[i]] = m[s[i]] + 1; else m.Add(s[i], 1); } // Iterate over frequency // if we not get a character // frequency prime then we // find the closest // prime and add foreach (KeyValuePair< char , int > x in m) { int h = x.Value; if (cspf[h] != -1) { k = k + cspf[h]; } } return k; } // Function to find the // minimum number of operations static void minOper(String s) { int []spf = new int [s.Length + 1]; int []cspf = new int [s.Length + 1]; // Function called to create // the spf spf_array(spf, s.Length + 1); // Function called to // create the cspf closest_prime_spf(spf, cspf, s.Length + 1); Console.Write(minimum_operation( cspf, s) + "\n" ); } // Driver Code public static void Main(String[] args) { // Input String String s = "aaaaaaaaabbcccccc" ; minOper(s); } } // This code is contributed by shikhasingrajput |
Javascript
<script> // JavaScript code for the // above approach // Using the sieve to find // the prime factors. function spf_array(spf, d) { spf[1] = 1; var i = 0; // Setting every number // as prime number initially for (i = 2; i < d; i++) { spf[i] = i; } // Removing the even numbers as // they cannot be prime except 2 for (i = 2; i < d; i = i + 2) { spf[i] = 2; } for (i = 3; i * i <= d; i++) { // If they are prime if (spf[i] === i) { var j; // Iterating the loop for // prime and eliminate all // the multiples of three for (j = i * i; j < d; j = j + i) { if (spf[j] === j) { spf[j] = i; } } } } } // Function to find the closest // prime number of every // number upto N (size of the String) function closest_prime_spf(spf, cspf, d) { // For the base case cspf[1] = 1; var i = 0, k = 0; // Iterating to find the // distance from the // lesser nearest prime for (i = 2; i < d; i++) { if (spf[i] !== i) { cspf[i] = Math.abs(i - k); } else { cspf[i] = -1; k = i; } } // Iterating to find the // distance from the // lesser nearest prime for (i = d - 1; i >= 2; i--) { if (spf[i] !== i) { if (cspf[i] > Math.abs(k - i)) { cspf[i] = Math.abs(k - i); } } else { k = i; } } } // Function to find the // minimum operation function minimum_operation(cspf, s) { // Created map to find the // frequency of distinct characters var m = {}; // Variable to iterate and // holding the minimum operation var i = 0, k = 0; // Loop for calculation // frequency for (i = 0; i < s.length; i++) { if (m.hasOwnProperty(s[i])) m[s[i]] = m[s[i]] + 1; else m[s[i]] = 1; } // Iterate over frequency // if we not get a character // frequency prime then we // find the closest // prime and add for (const [key, value] of Object.entries(m)) { var h = value; if (cspf[h] !== -1) { k = k + cspf[h]; } } return k; } // Function to find the // minimum number of operations function minOper(s) { var spf = new Array(s.length + 1).fill(0); var cspf = new Array(s.length + 1).fill(0); // Function called to create // the spf spf_array(spf, s.length + 1); // Function called to // create the cspf closest_prime_spf(spf, cspf, s.length + 1); document.write(minimum_operation(cspf, s) + "<br>" ); } // Driver Code // Input String var s = "aaaaaaaaabbcccccc" ; minOper(s); </script> |
3
Time complexity: O(N * log(log(N)))
Auxiliary Space complexity: O(N)
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!