Description:
Count the number of prime numbers less than a non-negative number, n
class Solution {
public:
void arrset(int *a, int val, int length) {
for(int i=0; i<length; ++i) {
*(a+i)=val;
}
}
int countPrimes(const int n) {
if(n <= 2) {
return 0;
}
for( int i = 2; i < n; ++i) {
if( m[i] == false) {
for( int j = i+1; j < n; ++j) {
if( j % i == 0)
helperArr[j] = 0;
}
}
}
int count=0;
for( i=2; i < n; ++i) {
if(helperArr[i] != 0)
++count;
}
return count;
}
};
上述算法超时。
改进算法:将内置循环j++改为j+=i。疑问:
class Solution {
public:
void arrset(int *a, int val, long length) {
for(int i=0; i<length; ++i) {
*(a+i)=val;
}
}
int countPrimes(const int n) {
if(n <= 2) {
return 0;
}
int *helperArr = new int[n];
arrset(helperArr, 1, n);//1 means prime
for( long i = 2; i < n; ++i) {
if( helperArr[i] == 1) {
for( long j = 2*i; j < n; j+=i) {
helperArr[j] = 0;
}
}
}
int count=0;
for( int i=2; i < n; ++i) {
if(helperArr[i] != 0)
++count;
}
return count;
}
};
高手写的:
class Solution {
public:
int countPrimes(int n) {
bool *p = new bool[n];
memset(p, true, sizeof(bool) * n);
for (int i = 2; i * i < n; ++i) {
if (p[i]) for (int j = 2; i * j < n; ++j) {
p[i * j] = false;
}
}
int cnt = 0;
for (int i = 2; i < n; ++i) if (p[i]) ++cnt;
delete [] p;
return cnt;
}
};
对于一个合数,上述方法会重复的标记,
快速线性筛法:对于素数i,标记与比其小的素数乘积的合数。如5,只标记5×2,5×3和5×5。这样就可以避免重复标记的情况。
class Solution {
public:
void arrset(int *a, int val, int length) {
for(int i=0; i<length; ++i) {
*(a+i)=val;
}
}
int countPrimes(int N)
{
int cnt=0;
int *tag=new int[N];
arrset(tag, 1, N);
for(int i=2; i<N; ++i) {
if(tag[i])
tag[cnt++]=i;
for(int j=0; j<cnt &&tag[j]*i<N; ++j) {
tag[tag[j]*i]=0;
if(i%tag[j] == 0)
break;
}
return cnt;
}
};