[求效率最高的算法]求1~n内的所有质数

来源:互联网 发布:淘宝新卖家可以直播吗 编辑:程序博客网 时间:2024/05/20 20:22
 

【列出质数】

请列出1~n内的所有质数。

 

【问题背景】

这是以前在CSDN论坛上看到的一个面试官写给应聘者建议中说到的一个问题,他说自己找到了一种最简单的方法,当然具体是什么方法没写出来。大学的时候学Fortran,经常没事干就琢磨用程序解决实际问题,印象比较深刻的就是9行代码取出1~n内的所有质数,当时自认为是效率最高的代码,列出来和有兴趣的朋友一起讨论,同时欢迎指正。当然更希望能看到那位面试官的答案。

 

【普通做法】

最常见的做法就是通过求余实现。

        int max = 1000000;

 

        boolean[] primes = new boolean[max + 1];

        for (int i = 0; i < max + 1; i++)

            primes[i] = i % 2 != 0;

        primes[1] = false;

        primes[2] = true;

 

        for (int i = 5; i < max; i+=2) {

            if (!primes[i])

                continue;

 

            int sqrt = (int) Math.sqrt(i);

            for (int ii = 3; ii <= sqrt; ii++) {

                if (i % ii == 0) {

                    primes[i] = false;

                    break;

                }

            }

        }

 

        int count = 1;

        for (int i = 3; i < max + 1; i+=2){

            if (primes[i]) count++;

        }

        System.out.println(max+"范围内的质数个数为:"+count);

 

输出结果:78498

    计算用时:759   ms

 

【筛法】

下面通过筛法来实现。

          int max = 1000000;

 

    boolean[] primes = new boolean[max + 1];

    for (int i = 0; i < max + 1; i++)

            primes[i] = i % 2 != 0;

    primes[1] = false;

    primes[2] = true;

 

    int kk = 3;

    int sqrt = (int) Math.sqrt(max);

   

   

    do {

            for (int i = kk * kk; i < max + 1; i += 2 * kk)

                primes[i] = false;

 

            do {

                kk += 2;

            }

            while (!primes[kk] && kk <= sqrt);

        }while (kk <= sqrt);

 

        int count = 1;

        for (int i = 3; i < max + 1; i+=2){

            if (primes[i])

                count++;

        }

        System.out.println(max+"范围内的质数个数为:"+count);

 

输出结果:78498

    计算用时:15   ms

 

【简单分析】

         [1]筛法很浪费空间。

[2]对于寻找1~n以内的所有质数,筛法无疑是最快的,因为它几乎不用任何运算就可以将某个质数的所有倍数排除掉。

[3]那位面试官说找到了最简单的方法,我认为只可能是对

for (int i = kk * kk; i < max + 1; i += 2 * kk)

进行改进,考虑过很长时间,不知道该如何改进。

原创粉丝点击