LeetCode 204. 计数质数

两种筛法

埃氏筛法

筛掉所有质数的倍数。每找到一个质数就把它所有的倍数筛掉。

class Solution {
    public int countPrimes(int n) {
        int[] primes = new int[n + 1];
        int cnt = 0;
        boolean[] st = new boolean[n + 1];
        for(int i = 2; i < n; i++){
            if(!st[i]){
                primes[cnt ++] = i;
                for(int j = i + i; j < n; j += i) st[j] = true;
            }
        }
        return cnt;
    }
}

时间复杂度

O ( n / 2 + n / 3 + n / 5 + . . . ) = O ( n l o g l o g n ) O(n / 2 + n / 3 + n / 5 + ...) = O(nloglogn) O(n/2+n/3+n/5+...)=O(nloglogn)

线性筛

每次只拿最小质因子筛掉合数,换言之,如果一个数被筛掉了,那么一定是被它的最小质因子筛掉的。

  1. i i%primes[j]!=0 i时,说明此时遍历到的 p r i m e s [ j ] primes[j] primes[j]不是i的质因子,那么只可能是此时的 p r i m e s [ j ] < i primes[j]<i primes[j]<i的最小质因子,所以 p r i m e s [ j ] ∗ i primes[j]*i primes[j]i的最小质因子就是 p r i m e s [ j ] primes[j] primes[j];
  2. 当有 i i%primes[j]==0 i时,说明 i i i的最小质因子是 p r i m e s [ j ] primes[j] primes[j],因此KaTeX parse error: Undefined control sequence: \* at position 11: primes[j] \̲*̲ i的最小质因子也就应该是 p r i m e [ j ] prime[j] prime[j],之后接着用 s t [ p r i m e s [ j + 1 ] ∗ i ] = t r u e st[primes[j+1]*i]=true st[primes[j+1]i]=true去筛合数时,就不是用最小质因子去更新了,因为 i i i有最小质因子 p r i m e s [ j ] < p r i m e s [ j + 1 ] primes[j]<primes[j+1] primes[j]<primes[j+1],此时的 p r i m e s [ j + 1 ] primes[j+1] primes[j+1]不是 p r i m e s [ j + 1 ] ∗ i primes[j+1]*i primes[j+1]i的最小质因子,此时就应该退出循环,避免之后重复进行筛选。
class Solution {
    public int countPrimes(int n) {
        int[] primes = new int[n + 1];
        int cnt = 0;
        boolean[] st = new boolean[n + 1];
        for(int i = 2; i < n; i++){
            if(!st[i]) primes[cnt ++] = i;
            for(int j = 0; primes[j] <= n / i; j ++) {
                st[i * primes[j]] = true;
                if(i % primes[j] == 0) break;
            }
        }
        return cnt;
    }
}

时间复杂度

每个数只会被自己的最小质因子筛掉一次,因此是线性时间复杂度 O ( n ) O(n) O(n)

我的博客:https://me.csdn.net/qq_20067165?ref=miniprofile

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值