时间复杂度通过所有前面的素数进行试验除法找到n个素数

时间:2017-06-21 19:28:45

标签: c time-complexity big-o primes

问题:查找 n 素数。

#include<stdio.h>
#include<stdlib.h>

void firstnprimes(int *a, int n){

    if (n < 1){
        printf("INVALID");
        return;
    }

    int i = 0, j, k;                // i is the primes counter

    for (j = 2; i != n; j++){       // j is a candidate number

        for (k = 0; k < i; k++)
        {
            if (j % a[k] == 0)      // a[k] is k-th prime
                break;
        }

        if (k == i)                 // end-of-loop was reached
            a[i++] = j;             // record the i-th prime, j
    }
    return;
}

int main(){
    int n;
    scanf_s("%d",&n);
    int *a = (int *)malloc(n*sizeof(int));
    firstnprimes(a,n);
    for (int i = 0; i < n; i++)
        printf("%d\n",a[i]);
    system("pause");
    return 0;
}

我的函数的内循环运行 i 次(最多),其中 i 是给定候选数下面的素数的数量,外循环运行for( n th prime number - 2 )次。

如何以Big O表示法推导出该算法的复杂性?

提前致谢。

2 个答案:

答案 0 :(得分:1)

素数定理表明,渐近地,小于n的素数的数量等于n/log n。因此,您的内部循环将运行The i * max = n / log n * n次(假设max = n)。

此外,您的外部循环运行大约n log n次,使得n / log n * n * n log n = n^3的总复杂度为Theta。换句话说,这不是最有效的算法。

请注意,周围有更好的近似值(例如n - 素数更接近:

n log n + n log log n - n + n log log n / log n + ...

但是,既然你只关心大O,这种近似就足够了。

此外,还有更好的算法可用于执行您要执行的操作。查看pseudoprimes主题,了解更多信息。

答案 1 :(得分:1)

在伪代码中,您的代码是

firstnprimes(n) = a[:n]   # array a's first n entries
    where
       i = 0
       a = [j for j in [2..]  
                if is_empty( [j for p in a[:i] if (j%p == 0)] )
                   && (++i) ]

(假设短路is_empty,一旦发现列表非空,就会返回false

它的作用是测试 2 中的每个候选编号及其所有前面的素数。

Melissa O&#39; Neill分析此算法in her widely known JFP article并将其复杂性推导为 O(n ^ 2)

基本上,生成的每个 n 素数都与它之前的所有素数配对(通过测试)(即 k-1 素数,对于 k th prime)和算术级数 0 ...(n-1)之和为(n-1)n / 2 这是 O(n ^ 2);并且她表明复合材料没有贡献任何比总和更重要的术语,因为在去往 n th prime的途中有O(n log n) composites但是is_empty计算提前失败

这是怎么回事: m = n log n ,会有 m / 2 evens,其中每一个{{1}计算只需 1 步; m / 3 3 的倍数, 2 步骤; m / 5 3 步骤;等。

复合材料的总贡献高估不处理多重性(基本上,计算 15 两次,作为 3的倍数 5 等),是:

is_empty

不等式可以在Wolfram Alpha cloud sandbox上作为SUM{i = 1, ..., n} (i m / p_i) // p_i is the i-th prime = m SUM{i = 1, ..., n} (i / p_i) = n log(n) SUM{i = 1, ..., n} (i / p_i) < n log(n) (n / log(n)) // for n > 14,000 = n^2 进行测试( 0.99921 ,对于更大的 n 进行测试,测试到 n = 2,000,000 ,其中 0.963554 )。