给定一个整数数组arr [] ,任务是计算将每个数组元素转换为最接近的素数所需的最小更改数。
例子:
Input: arr[] = {4, 25, 13, 6, 20}
Output: 5
Explanation:
- 1 increment required to convert 4 to its nearest prime 5.
- 2 decrements required to convert 25 to its nearest prime 23.
- 13 itself is a prime.
- 1 increment required to convert 6 to its nearest prime 7.
- 1 decrement required to convert 20 to its nearest prime 19.
Hence, required number of changes = 1 + 2 + 0 + 1 + 1 = 5
Input: arr[] = {1, 2, 9}
Output: 3
Explanation:
- 1 increment required to convert 1 to its nearest prime 2.
- 2 itself is a prime.
- 2 increments required to convert 9 to its nearest prime 11.
Hence, required number of changes = 1 + 0 + 2 = 3
天真的方法:
遍历数组,对于每个数组元素,从arr [i] + 1开始找到其最右边的素数,从arr [i] – 1开始找到其最左边的素数。计算完后,计算它们与arr [i]的差并考虑较小的差异。所有这些差异的总和给出了期望的输出。
时间复杂度: O(N * maxi 2 ),其中maxi表示数组中的最大元素。
高效方法:
可以使用Eratosthenes筛子解决此问题。请按照以下步骤解决问题:
- 从给定的数组中找到最大的元素。
- 令maxi为数组中存在的最大元素。生成[1,2 * maxi]范围内的所有素数并存储它们。
- 遍历数组,并使用lower_bound(例如x)为每个数组元素找到下一个更大质数的索引。
- 计算arr [i]和素数[x]之间以及arr [i]和素数[x – 1]之间的绝对差。
- 将两者中的最小值相加到ans 。
- 遍历数组后,打印ans的最终值作为答案。
下面是上述方法的实现:
C++
// C++ Program to implement
// the above approach
#include
using namespace std;
// Function to generate all primes
vector SieveOfEratosthenes(int n)
{
bool prime[2 * n + 1];
memset(prime, true, sizeof(prime));
for (int p = 2; p * p <= 2 * n; p++) {
// If p is a prime
if (prime[p] == true) {
// Mark all its multiples
// as non-prime
for (int i = p * p; i <= 2 * n;
i += p)
prime[i] = false;
}
}
vector primes;
// Store all prime numbers
for (int p = 2; p <= 2 * n; p++)
if (prime[p])
primes.push_back(p);
// Return the list of primes
return primes;
}
// Function to calculate the
// minimum increments to
// convert every array elements
// to a prime
int minChanges(vector arr)
{
int n = arr.size();
int ans = 0;
// Extract maximum element
// of the given array
int maxi = *max_element(arr.begin(),
arr.end());
vector primes
= SieveOfEratosthenes(maxi);
for (int i = 0; i < n; i++) {
// Extract the index which has
// the next greater prime
int x = lower_bound(primes.begin(),
primes.end(),
arr[i])
- primes.begin();
// Store the difference
// between the prime and
// the array element
int minm = abs(primes[x]
- arr[i]);
if (x > 1) {
minm = min(minm,
abs(primes[x - 1]
- arr[i]));
}
ans += minm;
}
return ans;
}
// Driver Code
int main()
{
vector arr
= { 4, 25, 13, 6, 20 };
cout << minChanges(arr);
return 0;
}
Java
// Java program to implement
// the above approach
import java.util.*;
import java.lang.*;
class GFG{
// Function to generate all primes
static ArrayList SieveOfEratosthenes(int n)
{
boolean[] prime = new boolean[2 * n + 1];
Arrays.fill(prime, true);
for(int p = 2; p * p <= 2 * n; p++)
{
// If p is a prime
if (prime[p] == true)
{
// Mark all its multiples
// as non-prime
for(int i = p * p;
i <= 2 * n; i += p)
prime[i] = false;
}
}
ArrayList primes = new ArrayList<>();
// Store all prime numbers
for(int p = 2; p <= 2 * n; p++)
if (prime[p])
primes.add(p);
// Return the list of primes
return primes;
}
// Function to calculate the
// minimum increments to
// convert every array elements
// to a prime
static int minChanges(int[] arr)
{
int n = arr.length;
int ans = 0;
// Extract maximum element
// of the given array
int maxi = arr[0];
for(int i = 1; i < arr.length; i++)
maxi = Math.max(maxi, arr[i]);
ArrayList primes = SieveOfEratosthenes(maxi);
for(int i = 0; i < n; i++)
{
// Extract the index which has
// the next greater prime
int x = -1;
for(int j = 0; j < primes.size(); j++)
{
if (arr[i] == primes.get(j))
{
x = j;
break;
}
else if (arr[i] < primes.get(j))
{
x = j;
break;
}
}
// Store the difference
// between the prime and
// the array element
int minm = Math.abs(primes.get(x) - arr[i]);
if (x > 1)
{
minm = Math.min(minm,
Math.abs(primes.get(x - 1) -
arr[i]));
}
ans += minm;
}
return ans;
}
// Driver code
public static void main (String[] args)
{
int[] arr = { 4, 25, 13, 6, 20 };
System.out.println(minChanges(arr));
}
}
// This code is contributed by offbeat
Python3
# Python program to implement
# the above approach
# Function to generate all primes
def SieveOfEratosthenes(n):
prime = [True for i in range(2 * n + 1)]
p = 2
while(p * p <= 2 * n):
# If p is a prime
if(prime[p] == True):
# Mark all its multiples
# as non-prime
i = p * p
while(i <= n * 2):
prime[i] = False
i += p
p += 1
primes = []
# Store all prime numbers
for p in range(2, (2 * n) + 1):
if(prime[p]):
primes.append(p)
# Return the list of primes
return primes
# Function to calculate the
# minimum increments to
# convert every array elements
# to a prime
def minChanges(arr):
n = len(arr)
ans = 0
# Extract maximum element
# of the given array
maxi = max(arr)
primes = SieveOfEratosthenes(maxi)
for i in range(n):
# Extract the index which has
# the next greater prime
x = -1
for j in range(len(primes)):
if(arr[i] == primes[j]):
x = j
break
elif(arr[i] < primes[j]):
x = j
break
# Store the difference
# between the prime and
# the array element
minm = abs(primes[x] - arr[i])
if(x > 1):
minm = min(minm, abs(primes[x - 1]-arr[i]))
ans += minm
return ans
# Driver code
arr = [4, 25, 13, 6, 20]
print(minChanges(arr))
# This code is contributed by avanitrachhadiya2155
C#
// C# program to implement
// the above approach
using System;
using System.Collections;
using System.Collections.Generic;
class GFG
{
// Function to generate all primes
static List SieveOfEratosthenes(int n)
{
bool[] prime = new bool[2 * n + 1];
Array.Fill(prime, true);
for(int p = 2; p * p <= 2 * n; p++)
{
// If p is a prime
if (prime[p] == true)
{
// Mark all its multiples
// as non-prime
for(int i = p * p; i <= 2 * n; i += p)
prime[i] = false;
}
}
List primes = new List();
// Store all prime numbers
for(int p = 2; p <= 2 * n; p++)
if (prime[p])
primes.Add(p);
// Return the list of primes
return primes;
}
// Function to calculate the
// minimum increments to
// convert every array elements
// to a prime
static int minChanges(int[] arr)
{
int n = arr.Length;
int ans = 0;
// Extract maximum element
// of the given array
int maxi = arr[0];
for(int i = 1; i < arr.Length; i++)
maxi = Math.Max(maxi, arr[i]);
List primes = SieveOfEratosthenes(maxi);
for(int i = 0; i < n; i++)
{
// Extract the index which has
// the next greater prime
int x = -1;
for(int j = 0; j < primes.Count; j++)
{
if (arr[i] == primes[j])
{
x = j;
break;
}
else if (arr[i] < primes[j])
{
x = j;
break;
}
}
// Store the difference
// between the prime and
// the array element
int minm = Math.Abs(primes[x]- arr[i]);
if (x > 1)
{
minm = Math.Min(minm,
Math.Abs(primes[x - 1] -
arr[i]));
}
ans += minm;
}
return ans;
}
// Driver code
public static void Main(string[] args)
{
int[] arr = { 4, 25, 13, 6, 20 };
Console.Write(minChanges(arr));
}
}
// This code is contributed by rutvik_56.
输出:
5
时间复杂度: O(log(log(N))+ O(NlogN)
辅助空间: O(N)