给定长度为N的字符串S ,任务是找到使每个不同字符的素数出现频率所需的最少操作。单个操作中字符的频率可以增加或减少1。
例子:
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 minimum number of operations needed is 2.
天真的方法:
查找字符串中每个字符的频率。设频率为X。查找大于X且小于X的质数。比较X与找到的两个质数之间的差,然后选择最接近的质数。将最接近的质数和X之差加到运算数量上。因此,将获得最少数量的操作。这是一种效率低下的方法,因为找不到质数的上下限是未知的。
高效的方法:
- 使用sieve算法查找所有不超过N的质数并将它们存储在数组中。
- 找出从i = 1到N的所有数字的最接近的较低质数,并将i与最接近的较低质数之间的差存储在数组arr1 []中。
- 找出从i = 1到N的所有数字的最接近的较高质数,并将i与最接近的较高质数之间的差存储在数组arr2 []中。
- 遍历字符串,找到的字符串中的所有字符迥异的频率和使用unordered_map来保存这些字符迥异的频率。
- 令任何不同字符的频率为X,然后从数组arr1 []和arr2 []中找出X与最接近的质数之间的距离。
- 选择两者之间较小的距离,并将此距离添加到操作数中。
- 对所有不同的字符执行此操作,最后打印操作数。
下面是上述方法的实现:
C++
// C++ code for the above approach
#include
#include
#include
using namespace std;
// using the seive to find
// the prime factors.
void spf_array(int spf[], int d)
{
spf[1] = 1;
int i = 0;
// setting every number
// as prime number initailly
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 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 chcarter
// 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 seive 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 initailly
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 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 chcarter
// frequency prime then we
// find the closest
// prime and add
for(Map.Entry 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 seive to find
# the prime factors.
def spf_array(spf, d):
spf[1] = 1
i = 0
# Setting every number as prime
# number initailly 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 chcarter 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 seive 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 initailly
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 m = new Dictionary();
// 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 chcarter
// frequency prime then we
// find the closest
// prime and add
foreach(KeyValuePair 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
3
时间复杂度: O(N * log(log(N)))
辅助空间复杂度: O(N)