返回
算法题解 LeetCode 204 统计所有小于非负整数 n 的质数数量
闲谈
2023-12-13 21:34:47
题目概述
LeetCode 第 204 题,题目如下:
给定一个非负整数 n,请统计一下从 0 到 n-1 中有多少个质数。
示例 1:
输入:n = 10
输出:4
解释:小于 10 的质数有 2、3、5、7,一共有 4 个。
示例 2:
输入:n = 0
输出:0
示例 3:
输入:n = 1
输出:0
解题思路
暴力枚举
暴力枚举,按题意从 0 到 n-1 依次遍历每个数字,并判断每个数字是否为质数。如果一个数字是质数,计数器加 1。最后返回计数器。
判断一个数字是否为质数,可以采用以下步骤:
- 从 2 开始,依次尝试将数字除以从 2 到数字的平方根(包括平方根)之间的所有整数。
- 如果能被除尽,则数字不是质数;否则,数字是质数。
def count_primes(n):
"""
统计小于非负整数 n 的质数的数量。
Args:
n: 非负整数。
Returns:
小于 n 的质数的数量。
"""
# 特殊情况
if n <= 1:
return 0
# 初始化计数器
count = 0
# 从 2 开始遍历
for i in range(2, n):
# 逐个数字判断是否是质数
is_prime = True
for j in range(2, int(i ** 0.5) + 1):
if i % j == 0:
is_prime = False
break
# 如果是质数,计数器加 1
if is_prime:
count += 1
return count
埃拉托斯特尼筛法
埃拉托斯特尼筛法是一种更有效的方法来统计小于 n 的质数的数量。它通过筛选出所有小于 n 的非质数来实现。
具体的步骤如下:
- 将一个列表初始化为 True,列表的长度为 n。
- 从 2 开始,将列表中所有数字的倍数(除了数字本身)标记为 False。
- 遍历列表,并将所有仍然标记为 True 的数字计数。
def count_primes(n):
"""
统计小于非负整数 n 的质数的数量。
Args:
n: 非负整数。
Returns:
小于 n 的质数的数量。
"""
# 特殊情况
if n <= 1:
return 0
# 初始化列表
is_prime = [True] * n
# 从 2 开始筛除非质数
for i in range(2, int(n ** 0.5) + 1):
if is_prime[i]:
for j in range(i * i, n, i):
is_prime[j] = False
# 计数质数
count = 0
for i in range(2, n):
if is_prime[i]:
count += 1
return count
复杂度分析
时间复杂度
暴力枚举的时间复杂度为 O(n log n),其中 n 为给定的整数。这是因为对于每个数字,都需要判断它是否为质数,这需要 O(log n) 的时间。
埃拉托斯特尼筛法的时间复杂度为 O(n log log n)。这是因为埃拉托斯特尼筛法只遍历了小于 n 的平方根的所有数字。
空间复杂度
暴力枚举的空间复杂度为 O(1),因为不需要额外的空间。
埃拉托斯特尼筛法的时间复杂度为 O(n),因为需要一个列表来存储是否为质数的信息。
总结
LeetCode 第 204 题,统计所有小于非负整数 n 的质数的数量。通过暴力枚举和埃拉托斯特尼筛法两种方法,可以解决该问题。暴力枚举的时间复杂度为 O(n log n),埃拉托斯特尼筛法的时间复杂度为 O(n log log n)。