出自leetcode第204题
题目描述:
统计所有小于非负整数 n 的质数的数量。
input : n = 10
output :4
解释:小于 10 的质数一共有 4 个, 它们是 2, 3, 5, 7
我们很容易想到就是暴力查找,从2到n-1找到满足条件的质数进行加加操作,很快写下了第一种思路:
class Solution {
public:
bool isPrime(int x) {
for (int i = 2; i * i <= x; ++i) {
if (x % i == 0) {
return false;
}
}
return true;
}
int countPrimes(int n) {
int ans = 0;
for (int i = 2; i < n; ++i) {
ans += isPrime(i);
}
return ans;
}
};
这种写法固然很好时间复杂度n * 根号n,但是当n很大的时候,就会造成超时。
我们有一种厄尔筛法。
如果一个数是质数,那么这个数的倍数一定不是质数,一个数是合数,这个数的倍数也一定不是合数。
我们需要一个状态数组来记录这个情况
vector<bool> signs(n, true);
我们如何去寻找到这个质数倍数呢?
我们从这个数向后 2倍开始,到3倍,到4倍,到5倍,直到临界值到达超过n的数值
代码
for(int j = i + i; j < n;j += i)
{
vec[j] = 0; //表示j这个数一定不会是质数
}
我们来看总体代码:
class Solution {
public:
int countPrimes(int n) {
int count = 0;
vector<bool> signs(n, true);
for (int i = 2; i < n; i++) {
if (signs[i]) {
count++;
for (int j = i + i; j < n; j += i) {
signs[j] = false;
}
}
}
return count;
}
};