📜  小于给定数n的最接近素数

📅  最后修改于: 2021-05-05 02:46:58             🧑  作者: Mango

给您一个数字n(3 <= n <10 ^ 6),您必须找到小于n的最接近素数?

例子:

Input : n = 10
Output: 7

Input : n = 17
Output: 13

Input : n = 30
Output: 29

解决此问题的简单方法是将n-1迭代为2,并针对每个数字检查其是否为质数。如果是素数,则将其返回并中断循环。如果只有一个查询,则此解决方案看起来不错。但是,如果有多个查询不同的n值,则效率不高。

解决此问题的有效方法是使用Sundaram的Sieve生成少于10 ^ 6的所有素数,然后以递增顺序存储在数组中。现在,应用修改后的二进制搜索来搜索小于n的最接近素数。该解决方案的时间复杂度为O(n log n + log n)= O(n log n)。

C++
// C++ program to find the nearest prime to n.
#include
#define MAX 1000000
using namespace std;
  
// array to store all primes less than 10^6
vector primes;
  
// Utility function of Sieve of Sundaram
void Sieve()
{
    int n = MAX;
  
    // In general Sieve of Sundaram, produces primes
    // smaller than (2*x + 2) for a number given
    // number x
    int nNew = sqrt(n);
  
    // This array is used to separate numbers of the
    // form i+j+2ij from others where  1 <= i <= j
    int marked[n/2+500] = {0};
  
    // eliminate indexes which does not produce primes
    for (int i=1; i<=(nNew-1)/2; i++)
        for (int j=(i*(i+1))<<1; j<=n/2; j=j+2*i+1)
            marked[j] = 1;
  
    // Since 2 is a prime number
    primes.push_back(2);
  
    // Remaining primes are of the form 2*i + 1 such
    // that marked[i] is false.
    for (int i=1; i<=n/2; i++)
        if (marked[i] == 0)
            primes.push_back(2*i + 1);
}
  
// modified binary search to find nearest prime less than N
int binarySearch(int left,int right,int n)
{
    if (left<=right)
    {
        int mid = (left + right)/2;
  
        // base condition is, if we are reaching at left
        // corner or right corner of primes[] array then
        // return that corner element because before or
        // after that we don't have any prime number in
        // primes array
        if (mid == 0 || mid == primes.size()-1)
            return primes[mid];
  
        // now if n is itself a prime so it will be present
        // in primes array and here we have to find nearest
        // prime less than n so we will return primes[mid-1]
        if (primes[mid] == n)
            return primes[mid-1];
  
        // now if primes[mid]n that
        // mean we reached at nearest prime
        if (primes[mid] < n && primes[mid+1] > n)
            return primes[mid];
        if (n < primes[mid])
            return binarySearch(left, mid-1, n);
        else
            return binarySearch(mid+1, right, n);
    }
    return 0;
}
  
// Driver program to run the case
int main()
{
    Sieve();
    int n = 17;
    cout << binarySearch(0, primes.size()-1, n);
    return 0;
}


Java
// Java program to find the nearest prime to n.
import java.util.*;
  
class GFG
{
      
static int MAX=1000000;
  
// array to store all primes less than 10^6
static ArrayList primes = new ArrayList();
  
// Utility function of Sieve of Sundaram
static void Sieve()
{
    int n = MAX;
  
    // In general Sieve of Sundaram, produces primes
    // smaller than (2*x + 2) for a number given
    // number x
    int nNew = (int)Math.sqrt(n);
  
    // This array is used to separate numbers of the
    // form i+j+2ij from others where 1 <= i <= j
    int[] marked = new int[n / 2 + 500];
  
    // eliminate indexes which does not produce primes
    for (int i = 1; i <= (nNew - 1) / 2; i++)
        for (int j = (i * (i + 1)) << 1; 
                j <= n / 2; j = j + 2 * i + 1)
            marked[j] = 1;
  
    // Since 2 is a prime number
    primes.add(2);
  
    // Remaining primes are of the form 2*i + 1 such
    // that marked[i] is false.
    for (int i = 1; i <= n / 2; i++)
        if (marked[i] == 0)
            primes.add(2 * i + 1);
}
  
// modified binary search to find nearest prime less than N
static int binarySearch(int left,int right,int n)
{
    if (left <= right)
    {
        int mid = (left + right) / 2;
  
        // base condition is, if we are reaching at left
        // corner or right corner of primes[] array then
        // return that corner element because before or
        // after that we don't have any prime number in
        // primes array
        if (mid == 0 || mid == primes.size() - 1)
            return primes.get(mid);
  
        // now if n is itself a prime so it will be present
        // in primes array and here we have to find nearest
        // prime less than n so we will return primes[mid-1]
        if (primes.get(mid) == n)
            return primes.get(mid - 1);
  
        // now if primes[mid]n that
        // mean we reached at nearest prime
        if (primes.get(mid) < n && primes.get(mid + 1) > n)
            return primes.get(mid);
        if (n < primes.get(mid))
            return binarySearch(left, mid - 1, n);
        else
            return binarySearch(mid + 1, right, n);
    }
    return 0;
}
  
// Driver code
public static void main (String[] args) 
{
    Sieve();
    int n = 17;
    System.out.println(binarySearch(0,
                        primes.size() - 1, n));
}
}
  
// This code is contributed by mits


Python3
# Python3 program to find the nearest
# prime to n.
import math
MAX = 10000;
  
# array to store all primes less
# than 10^6
primes = [];
  
# Utility function of Sieve of Sundaram
def Sieve():
  
    n = MAX;
  
    # In general Sieve of Sundaram, produces
    # primes smaller than (2*x + 2) for a 
    # number given number x
    nNew = int(math.sqrt(n));
  
    # This array is used to separate numbers
    # of the form i+j+2ij from others where 
    # 1 <= i <= j
    marked = [0] * (int(n / 2 + 500));
  
    # eliminate indexes which does not
    # produce primes
    for i in range(1, int((nNew - 1) / 2) + 1):
        for j in range(((i * (i + 1)) << 1), 
                        (int(n / 2) + 1), (2 * i + 1)):
            marked[j] = 1;
  
    # Since 2 is a prime number
    primes.append(2);
  
    # Remaining primes are of the form 
    # 2*i + 1 such that marked[i] is false.
    for i in range(1, int(n / 2) + 1):
        if (marked[i] == 0):
            primes.append(2 * i + 1);
  
# modified binary search to find nearest
# prime less than N
def binarySearch(left, right, n):
    if (left <= right):
        mid = int((left + right) / 2);
  
        # base condition is, if we are reaching 
        # at left corner or right corner of 
        # primes[] array then return that corner 
        # element because before or after that 
        # we don't have any prime number in
        # primes array
        if (mid == 0 or mid == len(primes) - 1):
            return primes[mid];
  
        # now if n is itself a prime so it will 
        # be present in primes array and here
        # we have to find nearest prime less than
        # n so we will return primes[mid-1]
        if (primes[mid] == n):
            return primes[mid - 1];
  
        # now if primes[mid]n 
        # that means we reached at nearest prime
        if (primes[mid] < n and primes[mid + 1] > n):
            return primes[mid];
        if (n < primes[mid]):
            return binarySearch(left, mid - 1, n);
        else:
            return binarySearch(mid + 1, right, n);
  
    return 0;
  
# Driver Code
Sieve();
n = 17;
print(binarySearch(0, len(primes) - 1, n));
      
# This code is contributed by chandan_jnu


C#
// C# program to find the nearest prime to n.
using System;
using System.Collections;
class GFG
{
      
static int MAX = 1000000;
  
// array to store all primes less than 10^6
static ArrayList primes = new ArrayList();
  
// Utility function of Sieve of Sundaram
static void Sieve()
{
    int n = MAX;
  
    // In general Sieve of Sundaram, produces 
    // primes smaller than (2*x + 2) for a 
    // number given number x
    int nNew = (int)Math.Sqrt(n);
  
    // This array is used to separate numbers of the
    // form i+j+2ij from others where 1 <= i <= j
    int[] marked = new int[n / 2 + 500];
  
    // eliminate indexes which does not produce primes
    for (int i = 1; i <= (nNew - 1) / 2; i++)
        for (int j = (i * (i + 1)) << 1; 
                 j <= n / 2; j = j + 2 * i + 1)
            marked[j] = 1;
  
    // Since 2 is a prime number
    primes.Add(2);
  
    // Remaining primes are of the form 2*i + 1 
    // such that marked[i] is false.
    for (int i = 1; i <= n / 2; i++)
        if (marked[i] == 0)
            primes.Add(2 * i + 1);
}
  
// modified binary search to find 
// nearest prime less than N
static int binarySearch(int left, int right, int n)
{
    if (left <= right)
    {
        int mid = (left + right) / 2;
  
        // base condition is, if we are reaching at left
        // corner or right corner of primes[] array then
        // return that corner element because before or
        // after that we don't have any prime number in
        // primes array
        if (mid == 0 || mid == primes.Count - 1)
            return (int)primes[mid];
  
        // now if n is itself a prime so it will be 
        // present in primes array and here we have 
        // to find nearest prime less than n so we
        // will return primes[mid-1]
        if ((int)primes[mid] == n)
            return (int)primes[mid - 1];
  
        // now if primes[mid]n 
        // that mean we reached at nearest prime
        if ((int)primes[mid] < n &&
            (int)primes[mid + 1] > n)
            return (int)primes[mid];
        if (n < (int)primes[mid])
            return binarySearch(left, mid - 1, n);
        else
            return binarySearch(mid + 1, right, n);
    }
    return 0;
}
  
// Driver code
static void Main() 
{
    Sieve();
    int n = 17;
    Console.WriteLine(binarySearch(0,
                      primes.Count - 1, n));
}
}
  
// This code is contributed by chandan_jnu


PHP
n 
        // that means we reached at nearest prime
        if ($primes[$mid] < $n && $primes[$mid + 1] > $n)
            return $primes[$mid];
        if ($n < $primes[$mid])
            return binarySearch($left, $mid - 1, $n);
        else
            return binarySearch($mid + 1, $right, $n);
    }
    return 0;
}
  
// Driver Code
Sieve();
$n = 17;
echo binarySearch(0, count($primes) - 1, $n);
      
// This code is contributed by chandan_jnu
?>


输出:

13

如果您有其他方法可以解决此问题,请分享评论。