📌  相关文章
📜  最小添加/删除字符以使每个字符的频率为素数

📅  最后修改于: 2021-05-14 00:43:05             🧑  作者: Mango

给定长度为N的字符串S ,任务是找到使每个不同字符的素数出现频率所需的最少操作。单个操作中字符的频率可以增加或减少1。

例子:

天真的方法:
查找字符串中每个字符的频率。设频率为X。查找大于X且小于X的质数。比较X与找到的两个质数之间的差,然后选择最接近的质数。将最接近的质数和X之差加到运算数量上。因此,将获得最少数量的操作。这是一种效率低下的方法,因为找不到质数的上下限是未知的。

高效的方法:

  1. 使用sieve算法查找所有不超过N的质数并将它们存储在数组中。
  2. 找出从i = 1到N的所有数字的最接近的较低质数,并将i与最接近的较低质数之间的差存储在数组arr1 []中
  3. 找出从i = 1到N的所有数字的最接近的较高质数,并将i与最接近的较高质数之间的差存储在数组arr2 []中
  4. 遍历字符串,找到的字符串中的所有字符迥异的频率和使用unordered_map来保存这些字符迥异的频率。
  5. 令任何不同字符的频率为X,然后从数组arr1 []arr2 []中找出X与最接近的质数之间的距离。
  6. 选择两者之间较小的距离,并将此距离添加到操作数中。
  7. 对所有不同的字符执行此操作,最后打印操作数。

下面是上述方法的实现:

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)