LeetCode 204. 计数质数 线性筛法详解 Java实现

204. 计数质数

题目来源

204. 计数质数

题目分析

给定一个整数 n,返回小于 n 的所有质数的数量。

题目难度

  • 难度:中等

题目标签

  • 标签:数学、筛选法

题目限制

  • 0 <= n <= 5 * 10^6

解题思路

思路:线性筛法

  1. 问题定义

    • 要求统计小于 n 的所有质数的数量。可以通过筛选法高效地找出质数。
  2. 核心算法

    • 使用线性筛法来筛选质数。相比于传统的埃拉托色尼筛法,线性筛法能够保证每个数只会被其最小质因数筛除一次,降低了时间复杂度。
  3. 关键步骤

    • 初始化一个数组 spf(Smallest Prime Factor,最小质因数),用于存储每个数的最小质因数。(也可以使用boolean数组isPrime记录哪个数是素数,但是最后还要再遍历一次数组计数)
    • 对于每个数 i,如果 spf[i] 等于 i,说明 i 是一个质数,将其加入质数列表。
    • 用当前质数去筛除后续的数,更新它们的 spf 值。

核心算法步骤

  1. 初始化数组

    • 初始化数组 spf,将每个数的最小质因数设为自身。
  2. 遍历筛选

    • 2 开始遍历到 n,如果 i 是质数(即 spf[i] == i),则将 i 加入质数列表。
    • i 乘以质数列表中的每个质数进行筛选,更新 spf
  3. 返回结果

    • 最终返回质数列表的大小,即为小于 n 的质数数量。

代码实现

以下是线性筛法的 Java 代码实现:

/**
 * 204. 计数质数
 * @param n 小于 n 的数
 * @return 质数的数量
 * @apiNote 线性筛法,时间复杂度O(n),空间复杂度O(n)
 */
public static int linearSieveOfEratosthenes(int n) {
    int[] spf = new int[n + 1]; // 最小质因数数组
    List<Integer> primes = new ArrayList<>();
    // 初始化每个数的最小质因数为自身
    for (int i = 2; i <= n; i++) {
        spf[i] = i;
    }
    // 遍历每个数,执行筛选
    for (int i = 2; i <= n; i++) {
        // 如果 i 是质数,则加入质数列表
        if (spf[i] == i) {
            primes.add(i);
        }
        // 筛选后续的数,更新它们的最小质因数
        for (Integer prime : primes) {
            if (i * prime > n) {
                break;
            }
            spf[i * prime] = prime;
            if (i % prime == 0) {
                break;
            }
        }
    }
    return primes.size();
}

代码解读

  • 线性筛法:通过最小质因数数组 spf 来筛选质数。每个数只会被其最小质因数筛除一次,确保算法在时间复杂度上的高效性。
  • 质数列表:用于存储所有筛选出的质数,最终通过质数列表的大小来得出质数的数量。

性能分析

  • 时间复杂度O(n),每个数只会被其最小质因数筛除一次,因此总的复杂度为线性。
  • 空间复杂度O(n),需要 O(n) 的空间来存储最小质因数数组 spf

测试用例

你可以使用以下测试用例来验证代码的正确性:

// 测试用例1
int n1 = 10;
System.out.println(linearSieveOfEratosthenes(n1)); // 输出: 4 (2, 3, 5, 7)

// 测试用例2
int n2 = 0;
System.out.println(linearSieveOfEratosthenes(n2)); // 输出: 0

// 测试用例3
int n3 = 1;
System.out.println(linearSieveOfEratosthenes(n3)); // 输出: 0

// 测试用例4
int n4 = 100;
System.out.println(linearSieveOfEratosthenes(n4)); // 输出: 25

扩展讨论

其他实现

  • 埃拉托色尼筛法:传统的埃拉托色尼筛法虽然简单,但时间复杂度为 O(n log log n),在大数据量时性能不如线性筛法。
  • 分段筛法:适用于超大范围的质数筛选,将筛选范围分为多段处理。

总结

这道题目考察了质数筛选的算法。通过线性筛法可以高效地计算小于 n 的质数数量,适用于大范围的质数筛选问题。


  • 14
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值