204. 计数质数
统计所有小于非负整数 n 的质数的数量。
示例 1:
输入:n = 10
输出:4
解释:小于 10 的质数一共有 4 个, 它们是 2, 3, 5, 7 。
示例 2:
输入:n = 0
输出:0
示例 3:
输入:n = 1
输出:0
提示:
0 <= n <= 5 * 106
题解:
方法一:枚举
由于最多有
y
=
x
∗
y
/
x
y=x*y/x
y=x∗y/x,所以
x
x
x的取值范围就在
[
1
,
s
q
r
t
(
y
)
]
[1,sqrt(y)]
[1,sqrt(y)]之间。如果大于
s
q
r
t
(
y
)
sqrt(y)
sqrt(y),那么
y
/
x
y/x
y/x一定在
[
1
,
s
q
r
t
(
y
)
]
[1,sqrt(y)]
[1,sqrt(y)]之内,只是符号换了位置。
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;
}
};
方法二:埃氏法
class Solution {
public:
int countPrimes(int n) {
vector<int> isPrime(n, 1);
int ans = 0;
for (int i = 2; i < n; ++i) {
if (isPrime[i]) {
ans += 1;
if ((long long)i * i < n) {
for (int j = i * i; j < n; j += i) {
isPrime[j] = 0;
}
}
}
}
return ans;
}
};
方法三:线性筛
class Solution {
public:
int countPrimes(int n) {
vector<int> primes;
vector<int> isPrime(n, 1);
for (int i = 2; i < n; ++i) {
if (isPrime[i]) {
primes.push_back(i);
}
for (int j = 0; j < primes.size() && i * primes[j] < n; ++j) {
isPrime[i * primes[j]] = 0;
if (i % primes[j] == 0) {//控制倍乘数值
break;
}
}
}
return primes.size();
}
};
其他人的解释:https://blog.csdn.net/qq_39763472/article/details/82428602
对照“埃氏法”与“线性筛”可以知道“埃氏法”某些数值是重复标记上“非质数”标记的,这样就造成了计算的冗余。
LeetCode官方表示这是面试当中不会问到的,本人也认为这个算法当中设计的数学关系过于专业和复杂,“积性函数”相关的内容就不深究了。