一、题目描述
二、解题思路
- 枚举优化:单纯的枚举是不行的,会超时,但是仔细观察可以发现我们只要枚举到对应数字的开方就可以了,以
Math.sqrt()
为界,只要前面的数字能被整除,那么这个数字就不是质数。 - 埃氏筛:一个比较巧妙的方法,假如一个数是质数,那么他的倍数都是合数,利用此特性,我们可以先额外创建一个数组对每个数进行标记,初始化都为质数,从2开始将每一个数的倍数的数所在标记设置为false,下次再遇到标记为false的数就可以不进行此处的循环了,借用一位大佬的图:
- 埃氏筛优化:从图中可以看出从2*j判断其实是冗余的,其中会有数字被重复标记,我们可以从j*j开始判断
- 线性筛:看完再补充
- 奇数筛:看完再补充
三、代码实现
方法一:
var countPrimes = function(n) {
let res = 0
const isPrimes = (i) => {
for(let j=2;j<=Math.sqrt(i);j++){
if(i%j==0)return false
}
return true
}
for(let r=2;r<n;r++){
if (isPrimes(r)) res++
}
return res
};
方法二:
var countPrimes = function(n) {
let res = 0
let isPrimes = new Array(n).fill(true)
for(let i=2;i<n;i++){
if(isPrimes[i]) res++
for(let j=2*i;j<n;j+=i) isPrimes[j]=false
}
return res
};
方法二·改进:
var countPrimes = function(n) {
let res = 0
let isPrimes = new Array(n).fill(true)
for(let i=2;i<n;i++){
if(isPrimes[i]) res++
for(let j=i*i;j<n;j+=i) isPrimes[j]=false
}
return res
};