算法学习|埃拉托斯特尼筛法

埃拉托斯特尼筛法(埃氏筛)

筛选出所有小于等于n的质数


步骤

  1. 初始化布尔数组:创建一个长度为 n+1 的数组 is_prime,初始时除 01 外,其他元素设为 True
  2. **标记非质数:从 2 开始遍历到 √n,若当前数 i 是质数,则将其所有倍数标记为非质数(从 开始)。
  3. 收集结果:遍历数组,收集所有标记为 True 的索引。

实现

def sieve_of_eratosthenes(n):
    if n < 2:
        return []
    # 初始化布尔数组,默认所有数为质数
    is_prime = [True] * (n + 1)
    is_prime[0], is_prime[1] = False, False  # 0和1不是质数
    
    # 遍历到sqrt(n)
    for i in range(2, int(n ** 0.5) + 1):
        if is_prime[i]:
            # 从i²开始标记,步长为i
            for j in range(i * i, n + 1, i):
                is_prime[j] = False
    
    # 收集所有质数
    primes = [i for i, prime in enumerate(is_prime) if prime]
    return primes

# 示例
n = 30
primes = sieve_of_eratosthenes(n)
print(primes)  # 输出 [2, 3, 5, 7, 11, 13, 17, 19, 23, 29](若n=30)

关键点解析

  1. 布尔数组初始化:

    is_prime = [True] * (n + 1)
    is_prime[0], is_prime[1] = False, False
    
    • 数组索引表示数值,is_prime[i]True 表示 i 是质数。
  2. 遍历范围优化:

    for i in range(2, int(n ** 0.5) + 1):
    
    • 只需遍历到 √n,因为若 n 有大于 √n 的因数,其对应的小因数已被处理。
  3. 标记倍数:

    for j in range(i * i, n + 1, i):
        is_prime[j] = False
    
    • 开始标记,因为小于 的倍数(如 i*2, i*3, ...)已被更小的质数处理过。

复杂度分析

  • 时间复杂度:O(n log log n),接近线性时间。
  • 空间复杂度:O(n),存储布尔数组。

应用场景

  • 快速生成质数表
  • 解决数学问题中的质数相关问题

优化扩展

预筛小质数:预先处理小的质数(如2,3,5),减少标记次数。

posted @ 2025-04-10 08:52  lumiere_cloud  阅读(101)  评论(0)    收藏  举报