Count Primes -- LeetCodes (primality test)

Description:

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

思路:这题第一种思路是写一个is_prime函数,来对每一个数验证一次是否是prime。

这个方法在这个题里表现不快,但也是一个学习is_prime函数的机会。

首先,验证一个数是不是prime,只需要用小于它的所有正整数全除一遍看是否能整除就行。实际上,我们只需要试验到sqrt(n),不需要到n-1。因为假如p * q = n的话,p和q是关于sqrt(n)对称的。

再然后,所有数都可以表示成6 * k + i的形式,其中k为整数,i = -1, 0, 1, 2, 3, 4。当i = 0, 2, 4时该数一定是偶数,不可能是prime。当i = 3时,这个数能被3整除,也不是。因此,若一个数是prime,除了2和3,它一定能被表示成 6 * k +/- 1的形式。

由此,我们获得了一个检测n是否是prime的思路:先验证n能否被2或者3整除。然后验证n能否被不大于sqrt(n)的所有能表示成6 * k +/- 1形式的数整除。

 1 bool is_prime(int n)
 2 {
 3     if (n <= 1) return false;
 4     else if (n <= 3) return true;
 5     else if (n % 2 == 0 || n % 3 == 0)
 6         return false;
 7     for (int i = 5; i * i <= n; i += 6)
 8         if (n % i == 0 || n % (i + 2) == 0)
 9             return false;
10     return true;
11 }

 

接下来介绍这个题里能用到的解法。

思路是我们先使用一个大小为n的数组,然后从2开始,将所有2的倍数全部标记成非prime。然后是3,将所有3的倍数全部标记成非prime。这里要注意的是,因为2 * 3已经在2的倍数那一步标注过了,因此这里从3的3倍开始。到4的时候,因为4已经被标注为非prime了,因此直接跳过。以此类推,将所有i从i倍开始的所有倍数标注为非prime。这个过程一直持续到i等于sqrt(n)。

 1 class Solution {
 2 public:
 3     int countPrimes(int n) {
 4         vector<bool> tab(n, true);
 5         for (int i = 2; i * i < n; i++)
 6             if (tab[i])
 7                 for (int j = i; i * j < n; j++)
 8                     tab[i * j] = false;
 9         int res = 0;
10         for (int i = 2; i < n; i++)
11             if (tab[i]) res++;
12         return res;
13     }
14 };

 

posted @ 2016-01-25 04:39  fenshen371  阅读(229)  评论(0编辑  收藏  举报