题目
方法一:枚举法
对于质数的定义,仅能被1和其本身整除的大于1的整数为质数。判断一个整数n是否为质数,只需看n是否可以被2~sqrt(n)的任意整数整除,若存在这个整数,则为合数,否则为质数。
public int countPrimes(int n) {
int sum = 0;
for(int i = 1; i < n; i++){
if( isPrimes(i)){
sum++;
}
}
return sum;
}
boolean isPrimes(int n){
if(n < 2)
return false;
int sq = (int) Math.sqrt(n) + 1;
for(int i = 2; i < sq; i++ ){
if(n % i == 0)
return false;
}
return true;
}
- 时间复杂度:没判断一次质数,需要 n \sqrt n n 次计算,总复杂度为 O ( n n ) O(n\sqrt n) O(nn )
- 空间复杂度:不需要额外的空间,O(1)
方法二:埃氏筛
如果n是一个质数,则n的倍数肯定为合数,即判断出了n为质数后,不必在判断2n,3n,4n…
又因为,任何一个合数都存在至少一个质数因数,即任何一个合数,都可以表示为一个质数的整倍数,所以所有的合数,都可以被一个小于它的质数的整倍数过滤掉。
因此,2是最小的质数,从2开始遍历到n,过滤标记出所有的合数,剩余的即全部的质数。
public int countPrimes(int n) {
int sum = 0;
boolean[] flag = new boolean[n+1]; // true代表合数
for(int i = 2; i < n; i++){
if(!flag[i]){
sum++;
for(int j = i; j < n ; j += i)
flag[j] = true;
}
}
return sum;
}
- 时间复杂度:O(nloglogn)
- 空间复杂度:O(n)