LeetCode 第 204 题 (Count Primes)

Posted liyuanbhu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode 第 204 题 (Count Primes)相关的知识,希望对你有一定的参考价值。

LeetCode 第 204 题 (Count Primes)

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

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

判断一个数字 n 是不是素数的简单方法是 用 n 去除 2,3,4,,n?1,如果都不能整除就说明这个数是素数。
按照这个思路可以写个简单的函数。

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

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

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;
}

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

 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 函数的时间复杂度是 O(n??),countPrimes 函数的时间复杂度是 O(n),所以整体的复杂度是 O(nn??)

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

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

    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;
}

除此之外,还有更快的判段一个数是否是素数的方法,时间复杂度为 O(1)。不过那种算法属于概率算法,有一定的小概率出错,以后有时间单独写一篇博客介绍那些方法。

以上是关于LeetCode 第 204 题 (Count Primes)的主要内容,如果未能解决你的问题,请参考以下文章

Leetcode 204. Count Primes

Leetcode problem-204 Count Primes 题解

LeetCode 204 Count Primes(质数计数)(*)

Leetcode_204_Count Primes

LeetCode----204. Count Primes(Java)

Java [Leetcode 204]Count Primes