您的位置:首页 > 其它

LeetCode 第 204 题 (Count Primes)

2016-07-01 12:37 501 查看

LeetCode 第 204 题 (Count Primes)


Description:

Count the number of prime numbers less than a non-negative number, n.



计算小于 N 的素数的个数。这道题目比较简单。但是想提高计算效率与需要费点脑筋。

判断一个数字 是不是素数的简单方法是 用 去除 ,如果都不能整除就说明这个数是素数。

按照这个思路可以写个简单的函数。

bool isPrime(int n)
{
if(n < 1) return false;
for (int i = 2; i < n; i++)
{
if (num % i == 0)
{
return false;
}
}
return true;
}


这个代码还可以优化一点。不用除到 ,只要除到 就可以了。

bool isPrime(int n)
{
if(n < 1) return false;
for (int i = 2; i * i < n; i++)
{
if (num % i == 0)
{
return false;
}
}
return true;
}


这个代码每次判断时都要算一遍 ,而第 69 题给出了一个计算 的快速算法,利用这个算法还可以再优化一点。

int mySqrt(int x)
{
if(x <= 0) return 0;
int a1 = 1;
int a2 = 46341 * 2 - 1;
unsigned int a, y;
if(a2 > x / 2) a2 = x;
do
{
a = (a1 + a2) / 2;
y = a * a;
if(y == x) return a;
if(y > x)
{
a2 = a;
}
else
{
a1 = a;
}
}while(a1 + 1 < a2);
a = (a1 + a2) / 2;
return a;
}
bool isPrime(int n)
{
if(n < 1) return false;
int sn = mySqrt(n);
for (int i = 2; i <= sn; i++)
{
if (num % i == 0)
{
return false;
}
}
return true;
}


之后计算素数个数的代码就可以写成这样。

int countPrimes(int n)
{
int count = 0;
for (int i = 1; i < n; i++)
{
if (isPrime(i)) count++;
}
return count;
}


即使写成这样,这个代码的计算复杂度还是有点大,isPrime 函数的时间复杂度是 ,countPrimes 函数的时间复杂度是 ,所以整体的复杂度是 。

实际上有一种简单的算法,时间复杂度可以降低到 。这种方法就是所谓的 Eratosthenes 筛选法(Sieve of Eratosthenes)。首先建立一张有 个元素的大表,表中每个元素都标记为 。那么这个表中 是第一个素数, 的倍数都不是素数,那么把表中 的倍数都标记为 。之后找表中在 后面第一个元素值为 的元素,这个元素就是第二个素数,当然这个数是 ,然后再将表中 的倍数全部标记为 。重复这个过程,就可以将表中所有的素数找出来了。按照这个思路写的代码如下:

int countPrimes(int n)
{
bool *primeTable = new bool
;

for (int i = 0; i < n; i++)
{
primeTable[i] = true;
}

int i = 2;
int count = 0;
while (i * i < n)
{
if (primeTable[i])
{
count++;
for (int j = i * i; j < n; j += i)
{
primeTable[j] = false;
}
}
i++;
}
while (i < n)
{
if(primeTable[i])
{
count++;
}
i++;
}
delete[] primeTable;
return count;
}


除此之外,还有更快的判段一个数是否是素数的方法,时间复杂度为 。不过那种算法属于概率算法,有一定的小概率出错,以后有时间单独写一篇博客介绍那些方法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: