package Algorithm;
import java.util.ArrayList;
/*
素数筛法,是一种快速“筛”出2~n之间所有素数的方法。
*/
public class PrimesFilter {
static int MAXN = 100001;
public static void main(String[] args) {
// 测试
int n = 50;
eratosthenes(n);
for(int i = 2; i < n; i++) {
// System.out.println(i + "\t" + (isnp[i] ? "不" : "") + "是质数");
if(!isnp[i]) System.out.print(i + " ");
}
System.out.println();
euler(n);
for(int i : primes) {
// System.out.println(i + "\t" + "是质数");
System.out.print(i+" ");
}
}
/*
朴素的筛法叫埃氏筛(the Sieve of Eratosthenes,埃拉托色尼筛),复杂度为O(nloglogn)
*/
static boolean[] isnp; // 不是素数
static void eratosthenes(int n) {
isnp = new boolean[MAXN];
for(int i = 2; i * i <= n; i++) {
// 如果是素数
if(!isnp[i]) {
// 它的倍数都不是素数,2i~(i-1)i在前面都已经被筛选过了,所以直接从i*i开始
for(int j = i * i; j <= n; j+=i)
isnp[j] = true;
}
}
}
/*
我们可能会发现,在筛的过程中我们会重复筛到同一个数,例如12同时被2和3筛到,30同时被2、3和5筛到。
所以我们引入欧拉筛,也叫线性筛,可以在 O(n) 时间内完成对2~n的筛选。
它的核心思想是:让每一个合数被其最小质因数筛到。
*/
// 质数表
static ArrayList<Integer> primes;
static void euler(int n) {
isnp = new boolean[MAXN];
primes = new ArrayList<>();
for(int i = 2; i <= n; i++) {
// 若是质数,直接加入质数表
if(!isnp[i]) primes.add(i);
// 遍历质数表
for(int p : primes) {
// 超出范围则跳出循环
if(i * p > n) break;
// 未超出循环,找到非质数
isnp[i * p] = true;
// 如果 i 的最小质因子已经在质数表中存在则无需加入质数表,并跳出循环
if(i % p == 0) break;
}
}
}
}
测试结果