素数筛(快速筛)-爱拉托斯特尼筛法+欧拉筛

如果题目只需要判断少量数字是否为素数,那么可以直接枚举因子从2一直到sqrt(n),看能否整除,当判断的数量较大的,需要使用筛法进行处理。

筛法求素数就是先认定所有的数是素数,再通过一些方法把合数踢掉。

埃拉托斯特尼筛法:

实例代码:

class Solution {
    public int countPrimes(int n) {
        if(n<=2){
            return 0;
        }
        boolean[] prime=new boolean[n];
        Arrays.fill(prime,true);
        for(int i=2;i*i<n;i++){
            for(int j=i*i;j<n;j+=i){
                prime[j]=false;
            }
        }
        int count=0;
        for(int i=2;i<n;i++){
            if(prime[i]){
                count++;
            }
        }
        return count;
    }
}

基本思路是,假如一个数是素数,那么这个数的倍数就是合数,这样就可以将这些合数筛掉。
通过仔细分析可以发现,这样的做法会造成重复筛合数,影响效率,比如30,在i=2的时候2 * 15判断了一次,在i=3的时候3 * 10又判断了一次,同理在i=5等位置进行了重复判断,因此便有了改进的筛法。

快速线性筛法(欧拉筛):

快速线性筛在普通筛法的基础上,消除了冗余:

class Solution {
    public int countPrimes(int n) {
        if(n<=2){
            return 0;
        }
        boolean[] prime=new boolean[n];
        int[] primes=new int[n];
        Arrays.fill(prime,true);
        int count=0;
        for(int i=2;i<n;i++){
            if(prime[i]){
                primes[count++]=i;
            }
            //关键点1
            for(int j=0;j<count&&i*primes[j]<n;j++){
                prime[i*primes[j]]=false;
                //关键点2
                if(i%primes[j]==0){
                    break;
                }
            }
        }
        return count;
    }
}

算法理解:

首先明确一个条件,任何合数都可以表示成一系列素数的乘积:

n = p 1 x 1 × p 2 x 2 × . . . × p n x n n=p_1^{x_1}\times p_2^{x_2}\times...\times p_n^{x_n} n=p1x1×p2x2×...×pnxn

从以上式子可以得到,p1是最小的因子,这样每个合数就有一个唯一的表示方法,不会重复:

最 小 的 素 数 ( p 1 ) × 其 他 ( n / p 1 ) 最小的素数(p_1) \times其他(n/p1) (p1)×(n/p1)

现在我们规定一个合数由两个数得到,那么合数有两种:

  • 素 数 × 素 数 素数\times素数 ×
  • 一 个 最 小 的 素 数 × 合 数 一个最小的素数\times合数 ×

筛除过程:

首先,不管i是否是素数,都会执行到“关键处1”。

  • 此时如果i是素数的话,一个大的素数i乘以不大于i的素数,这样筛除的数根之前的是不会重复的。筛除的数都是 N = p 1 × p 2 N=p_1\times p_2 N=p1×p2的形式, p 1 , p 2 p_1,p_2 p1,p2之间不相等。
  • 如果i是合数,此时i可以表示成上面递增素数相乘的形式, p 1 p_1 p1是最小的系数,根据“关键处2”的定义,当p1==prime[j]的时候,筛除就终止了,也就是说,只能筛除不大于 p 1 p_1 p1的质数*i

下面举个例子来直观理解:

i = 2 × 3 × 5 i=2\times3\times5 i=2×3×5

此时可以筛除 2 × i 2\times i 2×i,不能筛除 3 × i 3\times i 3×i

如果可以筛除 3 × i 3\times i 3×i的话,当 i ′ i' i等于 i ′ = 3 × 3 × 5 i'=3\times3\times5 i=3×3×5的时候,筛除 2 × i ′ 2\times i' 2×i就和前面重复了

练习题:
leetcode 204

爱拉托斯特尼筛+欧拉筛

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值