题目
给定整数 n
,返回 所有小于非负整数 n
的质数的数量 。
示例 1:
输入: n = 10
输出: 4
解释: 小于 10 的质数一共有 4 个, 它们是 2, 3, 5, 7 。
示例 2:
输入: n = 0
输出: 0
示例 3:
输入: n = 1
输出:0
提示:
0 <= n <= 5 * 106
题解
解题思路
本题可以使用暴力枚举的解法,代码也很容易实现,缺点是时间复杂度较大,尤其是处理大数的时候,在很多 OJ 系统都会超时。所以这里着重介绍一个常见的算法,该算法由希腊数学家厄拉多塞(Eratosthenes)提出,称为厄拉多塞筛法,简称埃氏筛。
一个质数 x,其的倍数(2x、3x、4x...)一定是合数,可以借助一个数组 isPrimes 存储 2 ~ n-1 各个数字是否是质数, 当一个数 x 被判断为质数,同时将其的倍数(2x、3x、....) 都标记为合数。
这样一来,在处理每个数时,直接通过 isPrimes 数组即可判断是否是质数,因为,如果是合数,那么一定会在处理前面的元素时就做了标记。
此外,还可以进一步提高效率,在处理质数 x 时,没有必要从 2x 开始把倍数标记为合数,而是应该从 x*x 开始,这是因为 2x ~ (x-1)*x 肯定在处理前面的数时已经被标记了,例如处理 2 时,由于 2x 是 2 的倍数,因此会将其标记为合数。
这种算法利用了数和数之间的联系,提供判断的效率,而不是每个数都枚举一遍。
代码
class Solution {
public int countPrimes(int n) {
int ans = 0;
int[] isPrimes = new int[n];
Arrays.fill(isPrimes, 1);
for (int x = 2; x < n; x++) {
if (isPrimes[x] == 1) {
ans++;
if (x * x < n) {
for (long i = (long)x * x; i < n; i += x) {
isPrimes[(int)i] = 0;
}
}
}
}
return ans;
}
}
复杂度分析
-
时间复杂度:O(nloglogn)\
-
空间复杂度:O(n)
优质项目推荐
推荐一个可用于练手、毕业设计参考、增加简历亮点的项目。
lemon-puls/txing-oj-backend: Txing 在线编程学习平台,集在线做题、编程竞赛、即时通讯、文章创作、视频教程、技术论坛为一体
公众号
有兴趣可以关注公众号一起学习更多的干货哈!