跳至主要內容

质数筛

大约 2 分钟algorithm质数筛

给出2种低时间复杂度快速筛选质数的方法

埃氏筛

埃氏筛,即 埃拉托斯特尼筛法,时间复杂度为 O(nlog(logn)),算法详情可参见wiki百科:埃拉托斯特尼筛法

public class AceSifter {
    /*
     * 返回 <= n 的所有质数
     *
     * @param n 上界
     */
    private static List<Integer> aceSifter(int n) {
        // 质数表
        List<Integer> primes = new ArrayList<>();

        // flag[i] = true: i为质数
        boolean[] flag = new boolean[n + 1];
        Arrays.fill(flag, true);

        // 0、1 不是质数
        flag[0] = flag[1] = false;

        // 将合数置为false
        for (int i = 2; i <= n; i++) {
            if (flag[i]) {
                // 注: j >= 0作用: 避免溢出
                for (int j = i * i; j >= 0 && j <= n; j += i) {
                    // 此处可加 if (flag[i]) 判断, 也可不加
                    flag[j] = false;
                }
                primes.add(i);
            }
        }
        return primes;
    }


    public static void main(String[] args) {
        List<Integer> primes = aceSifter(110);
        System.out.println(primes);
    }
}

欧拉筛/线性筛

欧拉筛,又名线性筛,时间复杂度为 O(n),算法详情可参考: 欧拉筛

public class EulerSifter {
    /**
     * 返回 <= n 的所有质数<br/>
     * @param n 上界
     */
    private static List<Integer> eulerSifter(int n) {
        // 质数表
        List<Integer> primes = new ArrayList<>();

        // flag[i] = true: i为质数
        boolean[] flag = new boolean[n + 1];
        Arrays.fill(flag, true);

        // 0、1 不是质数
        flag[0] = flag[1] = false;

        // 2 是质数
        flag[2] = true;
        for (int i = 2; i <= n; i++) {
            // 若i是「质数」,添加至质数表
            if (flag[i]) {
                primes.add(i);
            }
            // l是i的最小质因数,将 <=l(i的最小质因数)的质数与i相乘,并标记为false
            for (int l : primes) {
                if (i * l > n) {
                    break;
                }
                flag[i * l] = false;
                if (i % l == 0) {
                    break;
                }
            }
        }
        return primes;
    }


    public static void main(String[] args) {
        List<Integer> primes = eulerSifter(110);
        System.out.println(primes);
    }
}

参考文献

  1. https://zh.wikipedia.org/wiki/埃拉托斯特尼筛法open in new window
  2. https://www.bilibili.com/video/BV1H8411E7hn/?spm_id_from=333.999.0.0&vd_source=e9988d180a03a7b167558e2688c4362bopen in new window