题目描述
统计所有小于非负整数 n 的质数的数量。
示例 1: 输入:n = 10 输出:4 解释:小于 10 的质数一共有 4 个, 它们是 2, 3, 5, 7 。
示例 2: 输入:n = 0 输出:0
示例 3: 输入:n = 1 输出:0
提示:0 <= n <= 5 * 106
思路一:暴力破解(超时)
很直观的思路是我们枚举每个数判断其是不是质数。
考虑质数的定义:在大于 1 的自然数中,除了 1 和它本身以外不再有其他因数的自然数。因此对于每个数 x,我们可以从小到大枚举 [2,x-1] 中的每个数 y,判断 y 是否为 x 的因数。但这样判断一个数是否为质数的时间复杂度最差情况下会到 O(n),无法通过所有测试数据。
代码语言:javascript复制class Solution {
public:
int countPrimes(int n) {
int cnt=0;
for(int i=2;i<n;i ){
if(isPrime(i)){
cnt ;
}
}
return cnt;
}
bool isPrime(int m){
if(m==0||m==1){
return true;
}
for(int i=2;i<m;i ){
if(m%i==0){
return false;
}
}
return true;
}
};
复杂度分析
时间复杂度:O(n^2)。
空间复杂度:O(1)。
思路二:
考虑到如果 y 是 x的因数,那么 x/y也必然是 x 的因数,因此我们只要校验 y或者x/y即可。而如果我们每次选择校验两者中的较小数,则不难发现较小数一定落在 [2,sqrt(x)]的区间中,因此我们只需要枚举 [2,sqrt(x)]中的所有数即可,这样单次检查的时间复杂度从 O(n) 降低至了 O(sqr(n))
代码语言:javascript复制class Solution {
public:
int countPrimes(int n) {
int cnt=0;
for(int i=2;i<n;i ){
if(isPrime(i)){
cnt ;
}
}
return cnt;
}
bool isPrime(int m){
if(m==0||m==1){
return true;
}
for(int i=2;i*i<=m;i ){
if(m%i==0){
return false;
}
}
return true;
}
};
复杂度分析
时间复杂度:O(n*sqrt(n))。单个数检查的时间复杂度为 O(sqrt(n)),一共要检查 O(n) 个数,因此总时间复杂度为 O(n*sqrt(n))
空间复杂度:O(1)。