LeetCode 204. 计数质数(python)

该博客介绍了LeetCode第204题的解决方案,主要探讨如何统计小于非负整数n的质数数量。文中通过厄拉多塞筛法详细解释了解法1,并对比了两种超时的解法,讨论了质数的性质和优化策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接

题目描述:

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

示例:

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

解法1:
厄拉多塞筛法:
先将2-N的各数放入表中,然后在2的上面画一个圆圈,然后划去2的其他倍数;第一个既未画圈又没有被划去的数是3,将它画圈,再划去3的其他倍数;现在既未画圈又没有被划去的第一个数 是5,将它画圈,并划去5的其他倍数……依次类推,一直到所有小于或等于N的各数都画了圈或划去为止。这时,表中画了圈的以及未划去的那些数正好就是小于 N的素数。

在实现过程中,可以设置一个长度为n的数组,将所有值设为1.
然后从索引为2的数开始遍历数组,2是第一个质数,count加1,将所有索引2的倍数处的数置为0.直到2的倍数大于n为止
继续遍历数组,找到下一个不为0的数,count加1,将索引为该数字的倍数处的数字置为0,直到倍数大于n为止

class Solution(object):
    def countPrimes(self, n):
        """
        :type n: int
        :rtype: int
        """
        a=[1]*n
        count=0
        for i in range(2,n):
            if a[i]==1:
                count+=1 
                j=1
                while i*j<n:
                    a[i*j]=0
                    j+=1
        return count

在这里插入图片描述
评论区用时少的写法:

        arr=[1]*n
        arr[0],arr[1]=0,0
        for i in range(2,int(n**0.5)+1):
            if arr[i]:
                arr[i*i:n:i]=[0]*((n-1)//i-i+1)
        return sum(arr)

解法2:
直观写法,质数是只能被1和其本身整除:

这种做法本题超时

        num=0
        for i in range(2,n):
            flag=1
            for j in range(2,i):
                if i%j==0:
                    flag=0
                    break
            if flag==1:
                num+=1
        return num

解法3:
质数还有一个特点,就是它总是等于 6x-1 或者 6x+1,其中 x 是大于等于1的自然数。
首先 6x 肯定不是质数,因为它能被 6 整除;其次 6x+2 肯定也不是质数,因为它还能被2整除;依次类推,6x+3 肯定能被 3 整除;6x+4 肯定能被 2 整除。那么,就只有 6x+1 和 6x+5 (即等同于6x-1) 可能是质数了。所以循环的步长可以设为 6,然后每次只判断 6 两侧的数即可。

这种方法本题也超时

        count=0
        for num in range(n):
            if num==1:
                continue
            if num == 2 or num == 3:   # 两个较小的数进行处理
                count+=1
                continue
            if num % 6 != 1 and num % 6 != 5:  # 不在6的倍数的两侧的一定不是质数
                continue
            tmp = int(math.sqrt(num))
            flag=1
            for i in range(5, tmp+1):  # 在6的倍数两侧的也可能不是质数
                if num % i == 0:
                    flag=0
            if flag==1:count+=1
        return count
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值