o(n)时间判断素数的欧拉筛法

筛选素数,埃氏筛法虽然时间复杂度可以到达o(logn)的时间复杂度 ,但是仍有优化的空间,因为像6会被2筛出来一次,3筛出来一次,重复筛选,想要进一步提高就是解决这些重复筛选的情况。

一个合数,可以由两个数相乘得到,同样的,也可以表示成为一个最小素因子和另一个数相乘。对于每个合数,只有唯一确定的最小素因子。所以,如果每个合数都由它的最小素因子来筛选出来。那么就不会有埃氏筛法的重复现象。

上代码:


    int cnt = 0;
    for(int i=2; i<=n; i++)
    {
        if(!visit[n])//如果这个要考察的i并没有在之前被筛为合数,那它就是素数
        prime[cnt++] = i;
        for(int j=0; j<cnt; j++) //遍历每个素数//( i >= 这些素数)
        {
            if( i * prime[j] > n) //注释1
            break;
            visit[i * prime[j]] = true;
            if( i % prime[j] == 0) //如果两者为倍数。注释2
            break;
        }
    } 

看似是二层循环o(n^2)复杂度,实则为o(n),这两个break起了至关重要的作用。

注释1的break,限制了范围,超出了n,则循环不必进行了。

注释2的break,保证了合数只能会被最小素因子来筛选出来。在证明一个算法正确性的时候,关注局部,往往能让证明更加简

单。我们考察12这个合数,它可以由3*4 和 2 * 6算出 ,我们这个程序中,它只会被2*6筛选出来。

我们考察其为什么不会被3*4得到。当i = 4的情况,进入内层循环,遍历每个素数,当遍历到素数2后,i和当前素数成倍数,内循

环会因为注释二的代

码被中断。因为4 和 2 这个素数成倍数,所以如果循环继续没有中断,12就不会由最小素因子(2)得到了,而是由2的倍数4(i)筛出来了,所以这个break就保证了每个合数都由它的最小素因子筛选出来,而不会重复

既然保证了每个合数都由最小素因子筛出没有重复,因此时间复杂度就限制在了o(n)

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值