力扣(LeetCode)计数质数 个人题解

统计所有小于非负整数 的质数的数量。

示例:

输入: 10
输出: 4
解释: 小于 10 的质数一共有 4 个, 它们是 2, 3, 5, 7 。


一般方法,也就是一般人都会用的,将数从2到它本身逐个比较是否能被整除,就能得到结果。但这种方法复杂度是在0(n2)所以无法AC。

但是通过数学特性可以了解到,最多只要判断到这个数的开方数的时候,就可以知道这个数是否为质数了,所以复杂度减少了一半,也就可以让代码AC,但是时间用时也是很大的。

评论区学到的方法是,从2开始,剔除2到n中所有2的倍数,因为2的倍数都是非质数,然后找到3,同样剔除3的所有倍数,依次类推,得到最后的答案。

当然也可以应用数学特性将这个过程缩短,代码中不再演示

 

代码如下:(逐个比较)

import math


class Solution:
    def isPrime(self, n: int) -> bool:
        for i in range(2, math.floor(math.sqrt(n))+1):
            if n % i == 0:
                return False
        return True


    def countPrimes(self, n: int) -> int:
        count = 0
        for i in range(2, n):
            if Solution.isPrime(self, i):
                count += 1
        return count

 

代码如下:(剔除倍数)

class Solution:
    def countPrimes(self, n: int) -> int:
        if n < 3:
            return 0
        else:
            isPrime = [1] * n
            isPrime[0], isPrime[1] = 0, 0
            for i in range(2, n):
                t = 2
                if isPrime[i] == 1:
                    while i*t < n:
                        isPrime[i*t] = 0
                        t += 1
            return sum(isPrime)

 

剔除倍数的优化版本,摘自评论区:

# author: https://leetcode-cn.com/yuan-lei-yang/

def countPrimes(self, n: int) -> int:
        if n < 3:
            return 0     
        else:
            # 首先生成了一个全部为1的列表
            output = [1] * n
            # 因为0和1不是质数,所以列表的前两个位置赋值为0
            output[0],output[1] = 0,0
             # 此时从index = 2开始遍历,output[2]==1,即表明第一个质数为2,然后将2的倍数对应的索引
             # 全部赋值为0. 此时output[3] == 1,即表明下一个质数为3,同样划去3的倍数.以此类推.
            for i in range(2,int(n**0.5)+1): 
                if output[i] == 1:
                    output[i*i:n:i] = [0] * len(output[i*i:n:i])
         # 最后output中的数字1表明该位置上的索引数为质数,然后求和即可.
        return sum(output)

 

posted @ 2019-03-09 20:46  AXiangCoding  阅读(442)  评论(0编辑  收藏  举报