标签:prime 204 筛法 int 质数 list 列表 LeetCode
统计所有小于非负整数 n 的质数的数量。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/count-primes
暴力解法:
构建新列表存质数,遍历质数列表,如果n与质数列表的所有数相除余数都不等于0,则为质数,并增加质数列表,否则则不增加。
class Solution: def countPrimes(self, n: int) -> int: if n <=2: return 0 if n==3: return 1 list_ =[2] for item in range(3,n): for prime in list_: if item % prime ==0: break else: list_.append(item) return len(list_)
使用这种解法,力扣运行提示超时,那么该如何优化呢。
当prime>√n 时,则不需要加入质数列表参与除法。举个例子:
如果n为16,√16=4,4以内的质数只有2和3,此时16 能整除2和3,则16不是质数。
如果n为17,√17=4.123,5以内的质数只有2和3,此时17 不能整除2和3,则17是质数。
为什么不用考虑√n以上,参考定理:任何一个合数(非质数),都可以以唯一的形式被写成有限个质数的乘积。
class Solution: def countPrimes(self, n: int) -> int: if n <=2: return 0 if n==3: return 1 count =1 list_ =[2] for item in range(3,n): for prime in list_: if item % prime ==0: break else: count+=1 if prime < int(n**0.5)+1: list_.append(item) return count
通过优化,已经能跑通用例。
厄拉多塞筛法:
先将 2~n 的各个数放入表中,然后在2的上面画一个圆圈,然后划去2的其他倍数;第一个既未画圈又没有被划去的数是3,将它画圈,再划去3的其他倍数;现在既未画圈又没有被划去的第一个数 是5,将它画圈,并划去5的其他倍数……依次类推,一直到所有小于或等于 n 的各数都画了圈或划去为止。这时,表中画了圈的以及未划去的那些数正好就是小于 n 的素数。
class Solution: def countPrimes(self, n: int) -> int: if n < 3: return 0 list_a = [1] * n list_a[0], list_a[1] = 0, 0 for i in range(2, int(n**0.5)+1): if list_a[i] ==1: for j in range(i**2,n,i): list_a[j] =0 return sum(list_a)
欧拉筛法:
虽然欧拉筛法是线性的,但是由于厄拉多塞筛法进行了优化,还是比下面的代码稍快一些。
大致思路:
1、生成两个列表,一个用于存质数,一个用于标记是否是质数,先假设全部为质数
2、开始遍历n以内所有正整数i,如果没有被标记为非质数,则将已有的质数列表遍历j与i相乘,得出的数全部标记为合数(分解质因数原理),当i*j的值大于n时,就没有必要继续标记非质数了,因为遍历至n就停止了。
3、如若遍历中遇到数字被标记了非质数则跳过
class Solution: def countPrimes(self, n: int) -> int: if n < 3: return 0 prime_list = [] list_ = [1]*n for i in range(2, n): if list_[i]: prime_list.append(i) for j in prime_list: if j * i >= n: break list_[j * i] = 0 if i % j == 0: break return len(prime_list)
标签:prime,204,筛法,int,质数,list,列表,LeetCode 来源: https://www.cnblogs.com/zhhao/p/14079023.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。