本题使用传统方法,时间复杂度过高,会超时。从discuss学习了两种新的方法。
第一种方法:
class Solution {
public int countPrimes(int n) {
//Java对布尔数组初始化为false
boolean[] nf = new boolean[n];
if(n < 3) return 0;
int ans = 0;
for(int i = 2; i < n; i++){
if(nf[i] == false) ans++;
//将i的所有倍数都标记为不是素数
for(int j = 2; i * j < n; j++)
nf[i * j] = true;
}
return ans;
}
}
第一种改进的方法相对比较好懂,第二种如下
public class Solution {
/**
* 题目:Count the number of prime numbers less than a non-negative number, n
* @param n a non-negative integer
* @return the number of primes less than n
*/
public int countPrimes(int n) {
/**
* 根据题意知,n为0,1,2时结果均为0
*/
if (n < 3) return 0;
/**
* 结果c最大为n中包含的奇数的数量,因为偶数不可能是素数。
*/
int c = n / 2;
/**
* 数组s中元素为true表示该元素不是素数,并且在下面计算中偶数不考虑在内
*/
boolean[] s = new boolean[n];
/**
* i从3开始,并且每次只判断奇数,因此每次+2
*/
for (int i = 3; i * i < n; i += 2) {
if (s[i]) {
// 该元素不是素数,跳过
continue;
}
/**
* 从i开始,把所有含有i为因子的数全部标记为不是素数。
*
* i * i 以及 i * i + a * i都是含有i因子的数。
* 并且在下面循环中同样跳过偶数
* i为奇数,i*i也是奇数,但是奇数+奇数为偶数,故只循环i*i + 偶数的数
* 即只循环i*i + (even) * i
*/
for (int j = i * i; j < n; j += 2 * i) {
// 将s[j]设为不是素数,并且count减一
if (!s[j]) {
c--;
s[j] = true;
}
}
}
return c;
}
}