质数记数算法:埃拉托斯特尼筛法
质数计数算法:埃拉托斯特尼筛法
前置知识:质数(素数)是指:在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数。在判断一个数是否为质数时,常用的方法为:从2开始,遍历到\(\sqrt n\),如果没有可以整除的,则n是质数;反之,如果找到可以整除的,n就为合数.(对于大多数的暴力解法,也大多采用这种求法)
方法介绍
埃拉托斯特尼筛法是一种非常巧妙的经典算法。基本思想是:如果找到一个质数,那么对于这个质数的倍数就必定不是质数。所以,如果需要在一个范围[0,n]找到所有质数,那么我们只需要把不大于\(\sqrt n\)的所有质数的倍数取出,剩下的一定是质数,这就是筛法。
例如,对于质数7来说,它的倍数14,21,28等都一定不是质数,如果按照之前的暴力求解算法,那么我们在验证质数的时候,在这里就会进行一次多余的验证。按照埃拉托斯特尼筛法的思想,验证到一个质数时,我们就可以同时把它的倍数也筛选出去。
通常来说,一开始会创建两个列表(例如数组),一个用于存放所有待检查的数字,称为数字列表(包含质数和合数),另外一个用来存放已经发现的质数,称为质数列表。筛法的第一步是将数字列表中的第一个数字删除,把它添加到质数列表中(因为1不在定义范围之中,所以这里的第一个数是2),随后检查数字列表中所有2的倍数全部删除。之后再将数字列表中的第一个数删除,添加到质数列表中,同时在数字列表中删除倍数,循环操作直到数字列表为空。
方法改进
- 首先,因为所有的偶数都是2的倍数(好像是个废话),所以在开始生成数字列表的时候就可以只生成奇数,这样一来列表大小就就可以缩小一半
- 当数字列表中的首个元素的值大于最大数字的平方根的时候,算法就可以停止了。
- 另外还有一种取巧的方法,使用单独的布尔数组,将索引作为自然数,true表示是质数,false表示不是质数,这样就可以节省一个内存空间。
代码实现可以参考百度:埃拉托斯特尼筛法_百度百科
关联题目
Leetcode :204.计数质数
洛谷:P5723 质数口袋