题目描述

:::fold-green 相关原题

LeetCode 原题: ✅ 204. 计数质数

:::

给定非负整数 n,按升序返回闭区间 [0,n] 中的全部素数。

示例 1:

输入: n = 7
输出: [2,3,5,7]

提示:

  • 0 <= n <= 5000000
  • 0 和 1 不是素数。

题意分析

逐个试除会反复检查同一因子。筛法反过来枚举素数并标记其倍数,最后剩下的未标记位置就是素数;本题还要包含可能为素数的上界 n。

解法:埃氏筛

核心思路

[!blue]

composite[x] 表示 x 已被发现是合数。扫描到尚未标记的 i 时,它就是素数,用它标记后续倍数。

从 i*i 开始,是因为 2*i、3*i、…、(i-1)*i 都含有更小的因子,早已由前面的素数标记。只需处理到平方不超过 n 的 i,每个合数就会被至少一个较小因子覆盖。

最后从 2 扫描到 n,收集未标记的位置。本题包含上界 n,因此数组长度和循环上界都要覆盖 n,不能沿用“统计小于 n 的素数”的边界。

解题步骤

  1. n<2 时返回空结果,否则创建长度为 n+1 的合数标记数组。
  2. 从 2 开始扫描满足 i<=n/i 的数,已标记为合数的跳过。
  3. 对未标记的 i,从 i×i 开始按步长 i 标记所有不超过 n 的倍数。
  4. 从 2 到 n 升序收集未标记的数。

代码实现

class Solution {
    public List<Integer> listPrimes(int n) {
        if (n < 2) {
            return new ArrayList<>();
        }

        boolean[] composite = new boolean[n + 1];

        for (int i = 2; i <= n / i; i++) {
            if (composite[i]) {
                continue;
            }

            for (int multiple = i * i; multiple <= n; multiple += i) {
                composite[multiple] = true;
            }
        }

        List<Integer> primes = new ArrayList<>();

        for (int i = 2; i <= n; i++) {
            if (!composite[i]) {
                primes.add(i);
            }
        }

        return primes;
    }
}
func listPrimes(n int) []int {
    if n < 2 {
        return []int{}
    }

    composite := make([]bool, n+1)
    for i := 2; i <= n/i; i++ {
        if composite[i] {
            continue
        }
        for multiple := i * i; multiple <= n; multiple += i {
            composite[multiple] = true
        }
    }

    primes := []int{}
    for i := 2; i <= n; i++ {
        if !composite[i] {
            primes = append(primes, i)
        }
    }
    return primes
}

复杂度分析

  • 时间复杂度:$O(n\log\log n)$。
  • 空间复杂度:$O(n)$。

关键点总结

[!green]

埃氏筛标记合数,从每个质数的平方开始标记倍数;扫描包含 n 的整个范围,收集未标记的数。

易错点总结

[!yellow]

  • 上界 n 包含在结果范围中,数组和循环都要覆盖该下标。
  • 0 和 1 即使没有被标记也不是素数,收集必须从 2 开始。
  • 倍数标记从 i×i 开始;外层用 i<=n/i 判断平方边界,避免先计算过大的平方。

相似题目

题目 难度 关联与区别
204. 计数质数 中等 都可使用埃氏筛;该题统计严格小于 n 的素数个数,本题返回不大于 n 的全部素数,边界与输出形式不同。
转载与许可
作者
链接 https://hgnulb.github.io/blog/2026/389904329017
许可 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!