问题如题:N个人围城一圈报数(1/2/3/1/2/3/...),数到3的退出队列,求最后留下的人
#-*- coding:UTF-8 -*-
import time
def func1(n):
"""思路:删除原有列表中的凡是数到3及倍数的
使用临时序列存储要删除的数字,在每次循环完后删除需要去掉的数字"""
ltPserion = list(range(1,n+1))
pos = 0
while len(ltPserion)>1:
ltRemove = []
for i in ltPserion:
pos += 1
if pos%3==0:
ltRemove.append(i)
#print('ltPserion:',ltPserion,'将删除',ltRemove)
for i in ltRemove:
ltPserion.remove(i)
return ltPserion[0]
def func2(n):
"""思路:列表中凡是数到3及倍数
对于报数进行取余判断,如果是3的倍数就删除"""
ltPserion = list(range(1,n+1))
SayNo = 0
DelCount = 0
while DelCount1:
SayNo += 1
#print(ltPserion, '索引i=',i ,'当前数数SayNo=', SayNo, '人', ltPserion[i], end='')
if SayNo%3 == 0:
#print('删除',ltPserion[i], end='')
ltPserion.remove(ltPserion[i])
i-=1
i+=1
if i>=len(ltPserion):
i=0
#print()
return ltPserion[0]
def func4(n):
"""思路:列表中凡是数到3的就标记为删除
不用%取余,直接用if判断大于3就从1开始数数"""
ltPserion = list(range(1,n+1))
SayNo = 0
DelCount = 0
while DelCount
执行结果如下
>>>
func1: 92620 39.25819919960245
func2: 92620 0.31389559593181104
func3: 92620 42.987894393368286
func4: 92620 0.30714721310604887
>>>
分析:
对于上面的问题,采用了4个方法处理,求得的结果是方法4效率最高。
func1和func3类似,都是处理的list,删除报数为3的人,而func3更慢一点的原因是“if i>=len(ltPserion):”每次循环都获取了一次人员列表的长度。
func2和func4都没有删除数到3的人,只是在原队列中标记了去除的人,效率高了100倍,有此可见,程序执行循环耗费的时间,比队列的元素的删除省不少运行时间。func4比func2效率高一点点的原因是func2中“if SayNo%3==0:”使用了取余,取余操作的效率不如“if SayNo==3:SayNo = 1; else: SayNo += 1;”效率高。
当然func2、func4比起func1、func3也有弊端,就是占用的内存,func1、func3运行内存会不断的减小,而func2、func4不会减小。