【发布时间】:2011-07-17 21:01:35
【问题描述】:
给定一个整数 M。返回所有小于 M 的素数。
给出一个尽可能好的算法。需要考虑时间和空间复杂度。
【问题讨论】:
给定一个整数 M。返回所有小于 M 的素数。
给出一个尽可能好的算法。需要考虑时间和空间复杂度。
【问题讨论】:
埃拉托色尼筛法是一个很好的起点。
【讨论】:
一些额外的性能提示:
M 的平方根,因为每个合数至少有一个质因数小于或等于其平方根sqrt(M) 下面的每个数字)2 除外)【讨论】:
usual answer 是实现Sieve of Eratosthenes,但这实际上只是查找所有小于 N 的素数列表的解决方案。如果您想要primality tests 用于特定数字,对于大的数有更好的选择数字。
【讨论】:
Eratosthenes 的筛子很好。
【讨论】:
我是 C# 的新手程序员(也是 S.O. 的新手),所以这可能有点冗长。不过,我已经对此进行了测试,并且可以正常工作。
这是我想出的:
for (int i = 2; i <= n; i++)
{
while (n % i == 0)
{
Console.WriteLine(i.ToString());
n /= i;
}
}
Console.ReadLine();
【讨论】:
π(n) 计算小于或等于 n 的素数。 Pafnuty Chebyshev 已经证明,如果
limn→∞ π(n)/(n/ln(n))
存在,它是1。实际上有很多近似等于π(n)的值,如表所示。
它为这种数字格式提供了正确的素数数量。我希望这会有所帮助。
【讨论】:
您可以使用自下而上的动态编程方法(称为埃拉托色尼筛法)来做到这一点 基本上,您创建一个所有数字的布尔缓存,直到 n 并将每个数字的倍数标记为 not_prime。 进一步优化可以通过只检查到 sqrt(n) 来获得,因为任何合数都会有至少一个除数小于 sqrt(n)
public int countPrimes(int n) {
if(n==0){
return 0;
}else{
boolean[] isPrime=new boolean[n];
for(int i=2;i<n;i++){
isPrime[i]=true;
}
/* Using i*i<n instead of i<Math.sqrt(n)
to avoid the exepnsive sqrt operation */
for(int i=2;i*i<n;i++){
if(!isPrime[i]){
continue;
}
for(int j=i*i;j<n;j+=i){
isPrime[j]=false;
}
}
int counter=0;
for(int i=2;i<n;i++){
if(isPrime[i]){
counter++;
}
}
return counter;
}
}
【讨论】:
这是我为 Seive of Eratosthenes 开发的。当然,会有更好的实现。
//找到小于长度的素数个数
private static int findNumberOfPrimes(int length) {
int numberOfPrimes = 1;
if (length == 2) {
return 1;
}
int[] arr = new int[length];
//creating an array of numbers less than 'length'
for (int i = 0; i < arr.length; i++) {
arr[i] = i + 1;
}
//starting with first prime number 2, all the numbers divisible by 2(and upcoming) is replaced with -1
for (int i = 2; i < arr.length && arr[i] != -1; i++) {
for (int j = i; j < arr.length; j++) {
if (arr[j] % arr[i] == 0) {
arr[j] = -1;
numberOfPrimes += 1;
}
}
}
return numberOfPrimes;
}
【讨论】:
阿特金筛法也是在这种情况下实现的最佳算法,它只需要 O(N) 次操作和 O(N) 空间。算法和伪代码的详细解释请参考https://en.wikipedia.org/wiki/Sieve_of_Atkin。
【讨论】: