题:统计所有小于非负整数 n 的质数的数量。
1.枚举法
双重循环进行遍历,第一重遍历n,第二重判断n是否为素数,时间复杂度o(nn)o(n\sqrt{n})o(nn),空间复杂度为o(1).
int countPrimes(int n) {
int ans = 0;
int flag;
for (int i = 2; i < n; ++i) {
flag = 1;
for(int j = 2; j < int(sqrt(i)) + 1; j++)
{
if(i % j == 0)
{
flag = 0;
break;
}
}
if(flag)
{
ans++;
}
}
return ans;
}
2.埃氏筛
开一个长度为n的bool型数组isprime,第i位表示整数i是否为素数,初始化化为true,从2开始遍历,如果遇到一个数x为素数,计数值加1,则将isprime数组下标为2x,3x,4x……kx(kx<n<=kx+x)2x,3x,4x……kx(kx<n<=kx+x)2x,3x,4x……kx(kx<n<=kx+x)的值置为false。当然其也可以优化,因为2x,3x2x,3x2x,3x等,会由前面的素数进行更新,只需要从x∗x,(x+1)∗x.....x*x,(x+1)*x.....x∗x,(x+1)∗x.....开始更新及可。
时间复杂度:o(nloglog(n))o(nloglog(n))o(nloglog(n))(具体怎么计算我也不太了解),空间复杂度o(n)o(n)o(n).
class Solution {
public:
int countPrimes(int n) {
vector<int> isPrime(n, 1);
int ans = 0;
for (int i = 2; i < n; ++i) {
if (isPrime[i]) {
ans += 1;
if ((long long)i * i < n) {
for (int j = i * i; j < n; j += i) {
isPrime[j] = 0;
}
}
}
}
return ans;
}
};
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/count-primes/solution/ji-shu-zhi-shu-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
3.线性筛
埃氏筛也存在重复计算的情况,对于6,x=2x=2x=2和x=3x=3x=3时均对其进行了一次运算,导致了时间的浪费。我们考虑对于每一个合数只进行计算一次,使时间复杂度降到线性。对于任意一个合数x,我们能写成x=pyx=pyx=py的形式,其中p为x的最小素因子,我们只在遍历到y时,通过素数p对其进行一次操作。仍然从2开始到n进行遍历,如果isprime是true,将其加入prime容器,然后将对于当前所遍历到的i,在其中,我们用j遍历prime容器,将i∗prime[j]i*prime[j]i∗prime[j]置为false,当遇到i可以被prime[k]prime[k]prime[k]整除,即i=prime[k]∗ti=prime[k] * ti=prime[k]∗t的形式时退出,因为对于prime之后的素数来说i∗prime[j](j>k)i*prime[j](j>k)i∗prime[j](j>k)不应由prime[j]prime[j]prime[j]更新,而在遍历到prime[j]∗tprime[j]*tprime[j]∗t时由prime[k]prime[k]prime[k]更新(因为i∗prime[j]=prime[k]∗t∗prime[j]i*prime[j]=prime[k] * t*prime[j]i∗prime[j]=prime[k]∗t∗prime[j],而prime[k]<prime[j]prime[k]<prime[j]prime[k]<prime[j],由最小的素数更新)。
int countPrimes(int n) {
vector<int>prime;
bool *flag = new bool[n];//flag即为isprime
memset(flag,1,n*sizeof(bool));//初始化
for(int i = 2; i < n; i++)
{
if(flag[i])
{
prime.push_back(i);
}
for(int j = 0; j < prime.size() && i * prime[j] < n; j++)
{
flag[prime[j]*i] = false;
if(i % prime[j] ==0)
{
break;
}
}
}
return prime.size();
}