204. 计数质数

204. 计数质数

法一:暴力枚举

超时

class Solution:
    def countPrimes(self, n: int) -> int:
        #暴力枚举超时
        def isprime(x):
            if x==1:
                return False
            
            for i in range(2,int(sqrt(x))+1):
                if x%i==0:
                    return False
            return True
        if n in [0,1]:
            return 0
        cnt=0
        for i in range(2,n):
            if isprime(i):
                cnt+=1
        return cnt

法二:埃氏筛法

执行用时:1944 ms, 在所有 Python3 提交中击败了21.02%的用户
内存消耗:67.1 MB, 在所有 Python3 提交中击败了12.21%的用户

        #埃氏筛法
        if n in [0,1]:
            return 0
        #prime=[]
        cnt=0
        ht=[]#哈希列表初始化
        for i in range(n):
            ht.append(0)
        for i in range(1,n):
            if i==1:
                ht[1]=1
            if ht[i]==0:
                cnt+=1
                #prime.append(i)
                for j in range(i*i,n,i):#从i*i开始,而非i*2
                    ht[j]=1
        return cnt

法三:线性筛法

关键:每个合数只会被其最小的质因数删去,从而保证每个数只被标记一次,从而达到O(n)的时间复杂度。

执行用时:3580 ms, 在所有 Python3 提交中击败了8.66%的用户
内存消耗:79.8 MB, 在所有 Python3 提交中击败了8.91%的用户

class Solution:
    def countPrimes(self, n: int) -> int:
        if n in [0,1]:
            return 0
        cnt=0
        prime=[]
        ht=[]#哈希列表初始化
        for i in range(n):
            ht.append(0)
        for i in range(1,n):
            if i==1:
                ht[1]=1
            if ht[i]==0:
                prime.append(i)
            #线性筛的关键,i没有选择,乘的倍数有讲究。(质数序列)
            j=0
            while j<len(prime) and i*prime[j]<n:
                ht[i*prime[j]]=1
                if i%prime[j]==0:#i是合数则跳出.因为合数能删掉的数一定可以被它的质因子删掉。
                    break
                j+=1
        return len(prime)

法四:奇数筛法

非线性。比如45=3×15=5×9会被筛两次

1828 ms 67.2 MB Python3

class Solution:
    def countPrimes(self, n: int) -> int:
        if n in [0,1,2]:
            return 0
        ht=[]#哈希列表初始化
        for i in range(n):
            ht.append(0)
        for i in range(3,n,2):
            if ht[i]==0:
                #奇数筛的关键:从头到尾略过偶数
                j=i
                while i*j<n:
                    ht[i*j]=1
                    j+=2
        cnt=1#2
        for i in range(3,n,2):
            if ht[i]==0:
                cnt+=1
        return cnt
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值