@agf给出的解决方案是很好的,但是通过检查奇偶校验,对于任意奇数数,可以使运行时间快50%。由于奇数的因子本身总是奇数,所以在处理奇数时不必检查这些因子。
我刚开始自己解决Project Euler难题。在某些问题中,除数检查在两个嵌套的for循环中调用,因此该函数的性能至关重要。
结合这个事实和agf的优秀解决方案,我得到了这个函数:from math import sqrt
def factors(n):
step = 2 if n%2 else 1
return set(reduce(list.__add__,
([i, n//i] for i in range(1, int(sqrt(n))+1, step) if n % i == 0)))
但是,对于较小的数字(~<;100),此更改带来的额外开销可能会导致函数花费更长的时间。
为了检查速度,我做了一些测试。下面是使用的代码。为了产生不同的图,我相应地改变了X = range(1,100,1)。import timeit
from math import sqrt
from matplotlib.pyplot import plot, legend, show
def factors_1(n):
step = 2 if n%2 else 1
return set(reduce(list.__add__,
([i, n//i] for i in range(1, int(sqrt(n))+1, step) if n % i == 0)))
def factors_2(n):
return set(reduce(list.__add__,
([i, n//i] for i in range(1, int(sqrt(n)) + 1) if n % i == 0)))
X = range(1,100000,1000)
Y = []
for i in X:
f_1 = timeit.timeit('factors_1({})'.format(i), setup='from __main__ import factors_1', number=10000)
f_2 = timeit.timeit('factors_2({})'.format(i), setup='from __main__ import factors_2', number=10000)
Y.append(f_1/f_2)
plot(X,Y, label='Running time with/without parity check')
legend()
show()
X=范围(1100,1)
在这里没有显著差异,但如果数字越大,优势就越明显:
X=范围(11000001000)(仅奇数)
X=范围(2100001000)(仅偶数)
X=范围(11000001001)(交替奇偶校验)