对于初学python的小白而言,求质数是大家首先拿来练手的题目,通过求质数方法的优化,以加深对所学语法、数据结构的理解,下面我么就求质数的多种方法加深对for循环、列表、以及set的理解
1、普通求解
print(2,end=' ')
for i in range(3,100000,2):#排除偶数,只求奇数,计算量减少一半
for j in range(3,i**0.5+1,2):
if i%j == 0:
break
else:
print(i, end=' ')
这种方法主要是完成对for循环的应用,同时,通过处理,尽量减少for循环的迭代次数,提高运行效率。当然,由于所有质数都在6的倍数左右,因此,可以在计算中使用这一特性,代码如下:
print(2,3) #2和3特殊处理
i = 5
k = 2
while i <= 100000:
for j in range(3,int(i**0.5)+1,2):
if i%j == 0:
break
else:
print(i)
i += k #通过改变k的值,使i在6的倍数左右
k = 方6
2、使用列表的方法:
通过对质数性质的了解,我们了解到判断一个数是否为质数,我们只需要将其对比其小的数求余即可,因此,我们可以建立一个列表,将所求的质数添加到列表中,代码如下
lprime = [2,3]
i = 5
k = 2
while i <= 100:
for j in lprime:
if i%j == 0:
break
else:
lprime.append(i)
i += k
k = k^6
print(lprime)
使用列表的思想是将前一次的运算结果使用到下一次的运算中去,这在编程过程中可以减少计算次数,提高程序的运行效率,当然,以上代码还可以优化,在此不予赘述。
以上使用列表方法中,由于频繁的使用append方法更改列表长度,因此降低了程序的运行效率,那么,我么可不可以建立一个列表,不用去频繁更改其长度,只对其内部的值进行更改来求取质数呢?通过列表特性,我们发现,列表的索引和值可以给我们提供两个信息,因此,可以采用对列表标记的方法求取质数:
n = 100000
nums = [0]*(n+1) #建立一个列表,长度为质数求取范围
for i in range(2,int(n**0.5)+1): #将所有索引值为非质数的元素标记为1
if nums[i]:
continue
for j in range(i**2,n+1,i):
if nums[j]:
continue
nums[j] = 1
for i in range(2,n+1):
if not nums[i]:
pass
print(i)
通过使用列表标记的方法,一次性创建一个列表,其时间复杂度会大幅度降低,在此过程中,我们需要了解列表的特性,怎么样的程序才能降低程序的时间复杂度,同时,当空间复杂度和时间复杂度相冲突时,我们应该怎么样取取舍
3、使用set集合的方法
set时无序的、可变的、不重复的元素的集合,由于对set内元素的读取是通过hash值来实现的,因此读写速度特别快,我们可以根据这一特性来求质数
n = 100000
primeset = set(range(1,n,2))
m = int(n**0.5)+1
for i in range(3,m,2):
if i not in primeset:
continue
for j in range(i**2,n+1,i*2):
primeset.discard(j)
print(primeset)
以上程序利用了set内部元素可变、无序,读取删除快的特点,因此提高了程序效率
总结
(1)在初学阶段,我们更注重于如何去解决问题,使用最初级的手段解决复杂问题时,要注意不能缺项漏项,培养严谨的作风
(2)在使用语言为我们提供的内置数据结构时,要对数据结构有清晰的了解,这样才能写出高效的代码
(3)对一个问题的反复思考,对代码的反复改进,有助于加深对语言本身的理解,这对于初学阶段的人是十分必要的