算法基础之质数判定

质数:只能被 1 1 1 和自身整除的的自然数, 1 1 1 既不是质数也不是合数。

质数定理: 1 1 1 n n n 中最多有 n / l o g ( n ) n/log(n) n/log(n) 个质数。

质数判定通常有两类方法:试除法和筛质数。

试除法,顾名思义,对于 n n n,检查所有 2 ≤ m < n 2 ≤ m < n 2mn,是否存在 m m m n n n 的质数,若不存在则说明 n n n 是质数。试除法用于判断一个数是不是质数。

筛质数,筛选出小于等于 n n n 的质数/非质数。筛质数用于判断一批数是不是质数,常用的筛质数方法有埃氏筛法和线性筛法。

试除法

// 试除法
bool isPrime(int x) {
    if (x < 2)return false;
    for (int i = 2; i <= x / i; i++) {
        if(x%i==0)return false;
    }
    return true;
}
bool isPrime(int x) {
    if (x < 2)return false;
    for (int i = 2, k = sqrt(x); i <= k; i++) {
        if (x % i == 0)return false;
    }
    return true;
}

时间复杂度: O ( √ n ) O(√n) O(n)

空间复杂度: O ( 1 ) O(1) O(1)

埃氏筛法

基本思想:假设求范围小于等于 n n n 的质数,对于 2 ≤ m ≤ n 2≤m≤n 2mn 的每个数 m m m,将其 k k k 倍数( k > 1 k>1 k1)筛掉,剩下的就是质数。

// primes 记录已找到的每个质数
int primes[N], idx;
// notPrime[i]=true 表示 i 不是质数
bool notPrime[N];
void getPrimes(int n) {
    for (int i = 2; i <= n; ++i) {
        if (!notPrime[i]) {
            // 当轮到 i 时,如果 i 没有被筛掉,则 i 必为质数
            primes[idx++] = i;
            // 当i为质数时才需要筛掉它的倍数
            for (int j = i << 1; j <= n; j += i) {
                notPrime[j] = true;
            }
        }
    }
}

时间复杂度: O ( n l o g ( l o g ( l o g ( n ) ) ) O(nlog(log(log(n))) O(nlog(log(log(n)))

空间复杂度: O ( n ) O(n) O(n)

线性筛法

基本思想:假设求范围小于等于 n n n 的质数,对于 2 ≤ m ≤ k 2≤m≤k 2mk 的每个质数 m m m,将其 k k k 倍数筛掉,剩下的就是质数( k k k 2 2 2 n n n)。

// primes 记录已找到的每个质数
int primes[N], idx;
// notPrime[i]=true 表示 i 不是质数
bool notPrime[N];
void getPrimes(int n) {
    for (int i = 2; i <= n; ++i) {
        if (!notPrime[i]) primes[idx++] = i;
        // 筛掉目前所有质数的i倍
        for (int j = 0; primes[j] <= n / i; ++j) {
            notPrime[primes[j] * i] = true;
            if (i % primes[j] == 0)break;
            // 当i%pj=0时,pj一定是i的最小质因子,所以,pj一定是pj*i的最小质因子
            // 当i%pj!=0时,pj一定小于i的最小质因子,所以,pj一定是pj*i的最小质因子
            // 于是每个数只会被其最小质因子筛掉,也即不会重复被筛
        }
    }
}

时间复杂度: O ( n ) O(n) O(n)

空间复杂度: O ( n ) O(n) O(n)

END

文章文档:公众号 字节幺零二四 回复关键字可获取本文文档。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值