笔试中遇到的求质数

参考:http://blog.csdn.net/program_think/article/details/7032600/

昨天笔试遇到这个求质数的笔试题,自己用的纯暴力的解法,只考虑奇数,判断n 是否是素数的时候直接 3-n-1 来试除的。
后续还有优化,但是没有想出来。。。
参考这里:求质数算法的N种境界 (N > 10) ,竟然有这么多的优化。

1,试除法

在判断n 是否是质数的时候,只要循环求出它可能存在的因子,并试除即可。

1.1 优化1

对于 n 的因子,并不是从1-n-1,而是 1 - n/2。

  • 对于 n = a*b(a < b),对于a 其变化是 1 - square(n) 的,a 再变大,则 b 就会变小,这样b 就等于之前判断过的a了
  • 因为质数只有在奇数中产生,因此其因数不可能是偶数

所以在试除的时候只需要试除 1 - square(n)之间的奇数就可以,而不是 1 – n-1.

1.2 优化2

对于奇数中的倍数关系,不能被某个数整除,必然不能被其倍数整除。比如 不能被 3 整除,则在奇数中,也不能被 9 整除。所以试除范围仍然可以缩小
1 - square(n) 的奇数中中有因数的整数不用再试除—-就是合数,因为只要判断其因数是否可以被整除就可以了。

所以试除范围可以进一步缩小为1 - square(n)之间的质数。 而之前的质数是我们求过的,只要开一个数组保存即可。
arr[] 是保存的之前求出的素数。

    public static boolean helper(int n){
        for(int i =0;arr[i]<Math.sqrt(n);i++){
            if(n%arr[i] == 0) return false;         
        }
        return true;
    }

2,筛选法

 首先,2是公认最小的质数,所以,先把所有2的倍数去掉;然后剩下的那些大于2的数里面,最小的是3,所以3也是质数;然后把所有3的倍数都去掉,剩下的那些大于3的数里面,最小的是5,所以5也是质数……
  上述过程不断重复,就可以把某个范围内的合数全都除去(就像被筛子筛掉一样),剩下的就是质数了。

所以开一个 n+1 大小 的boolean 数组(i 保存在 arr[i]中,则求i 的倍数时,只要找下标为j*i的即可),奇数下标全部设为true,偶数下标为false。如果 arr[i] == true,将 arr[j*i] 的值全部设为false;

    public static void helper(int n){
        boolean [] arr = new boolean[n+1];
        for(int i=1;i<n+1;i+=2){
            arr[i]=true;
        }

        for(int j=0;j<n+1;j++){
            if(arr[j]){
                for(int k=2*i;k<n+1;K+=i){
                    arr[k]=false;
                }
            }
        }
    }

最后输出arr [] 为 true 的数值即可。

优化

同样,对于筛选法,1–n 中的整数,对于 square(n) 之后的整数 m,如果m = a*b(a > b),必然已经被 a 筛选过了,则 square(n) 之后的整数不必再对其倍数进行筛选。

for(int j=0;arr[j]*arr[j]<n+1;j++){
            if(arr[j]){
                for(int k=2*i;k<n+1;K+=i){
                    arr[k]=false;
                }
            }
        }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值