当遇到需要求一定范围内的素数来使用时,可以使用欧拉筛法求出范围内全部的素数,且时间复杂度为O(n),也称线性筛。
代码如下
public List<Integer> getPrimes(int n){
List<Integer> primes = new ArrayList<>();
boolean st[] = new boolean[n+1];
for(int i = 2; i <= n; i ++){
if(!st[i]){
primes.add(i);
}
for(int p : primes){
if(p * i > n)
break;
st[p * i] = true;
if(i % p == 0){
break;
}
}
}
return primes;
}
利用的思想即是每个质数的倍数都一定不是质数,因此可以从2开始向后标记,最后得到范围内全部的质数。
但为避免重复标记,通过 i % p == 0 实现每个合数都只被最小的质因数筛一次
i = 4时,此时primes = {2,3}
i * p = 8,8标记为合数,此时 4 % 2 == 0,即表示其后的合数可以用2筛去而非用4
即省略的筛是i = 4,p = 3,i * p = 12情况,12不必用4 * 3筛去,在后续处理中,12会由2筛去
i = 6时,此时primes = {2,3,5}
i * p = 12,12标记为合数,此时即实现了12是由它的最小质因数2筛去的,对于12只筛了一次