204. Count Primes

来源:互联网 发布:淘宝客交易成功后退款 编辑:程序博客网 时间:2024/05/22 16:59

这里写图片描述
题目大意:
给一个非负整数n,求小于n的素数的个数

思路:
第一反应是采用素数的定义来做。

(1)如果采用素数的定义,即不能被1和它本身整除,需要从2计算到它减一,举个栗子,如果要验证17是素数,则需要计算17 / 2,17 / 3,17 / 4 … 17 / 16,O(n)级别的复杂度。伪代码如下:

for(int i = 2; i < n; i++) {    // 此处是判断n是否可以被i整除的代码}

(2)当然,可以对其优化,我们知道,一个数不能被大于它1/2的数整除,(17的1/2是8.5) 17不能被9、10、11… 16 整除,因此可以减小循环的范围。伪代码如下:

for(int i = 2; i < n / 2 + 1; i++) {    // 此处是判断n是否可以被i整除的代码}

(3)继续优化。如果p、q的乘积为n,即p * q = n,令p为p、q中较小的那个即:p <= q,则可以推出 p <= sqrt(n),可以继续减小循环的范围。伪代码如下:

for(int i = 2; i < sqrt(n) + 1; i++) {    // 此处是判断n是否可以被i整除的代码}

(4)当然,我也没有这么傻,如果数据量大,使用上述的方法一定会超时,所以我打了个表。首先初始化一个数组arr,里面存布尔型变量,初始化时均未True,如果arr[i] = True,表示 i 是素数,False表示 i 不是素数。这里的思路是,首先假设所有数都是素数,然后把不是素数的逐个剔除,最后剩下的都是素数。很der的思路。对于一个i,它的倍数一定不是素数,根据这个原理写了一个从2到n的循环:

for(int i = 2; i < n; i++) {    for (int j = 2; i * j < n; j++) {        // i * j 一定不是素数        arr[i*j] = False;    }}

然后就这么交了,,一共20个用例,在第18个用例时,即当n = 999983,超时!
(5)其实仔细分析一下也可以看出问题,打表打得不对,有重复判断的现象,比如15这个数,在3上判断了一次,是3的5倍。在5上又判断了一次,是5的3倍,这样就重复判断了。对于5而言,不必再计算5 * 3了,直接从5 * 5开始计算就可以了。

Python代码:

import mathclass Solution(object):    def countPrimes(self, n):        """        :type n: int        :rtype: int        """        # 打表        arr = [True for i in range(n)]        m = int(math.sqrt(n)) + 1        for i in range(2, m):            if arr[i]:               for j in range(i*i, n, i):                   arr[j] = False         count = 0        for i in range(2, len(arr)):            if arr[i]:                count += 1                print(i)        return count
0 0
原创粉丝点击