【背景】
我需要從N遍歷到1,當我已經判斷N不符合要求時,我知道N的所有約數也是不符合的,所以所有N的約數也不用遍歷。因此,對於遍歷的每個N,我需要快速找到它的所有約數,放到一個集合里面,而當我遍歷到N'時,如果N'在集合里,我就不需要再進行判斷了(假設每次判斷所需要的時間遠遠大於約數的判斷),這樣我就節省了大量的時間。
【解決】
stackoverflow里面有個高效的答案,如下:
1 1 from functools import reduce 2 2 3 3 def factors(n): 4 4 return set(reduce(list.__add__, 5 5 ([i, n//i] for i in range(1, int(n**0.5) + 1) if n % i == 0)))
【解析】
1、欲找N的約數,只需要在N^1/2(根號N)范圍內找到半數的約數即可,剩下的半數(大約數)可直接通過N除以小的約數找到。
因此: range(1,int(n**0.5)+1) --> 半數(小約數)范圍
n %i == 0 --> 半數(小約數)數值
n // i --> 剩余半數(大約數)數值
2、將找到的所有約數對列表,展開為一個大的列表。
因此: reduce( list.__add__, (列表對) )
3、對於完全平方數,i == n//i,因此展開的列表中會有兩個一樣的數值。
因此: set(列表),去掉重復值。
【效率】
本機運行結果供參考。
1 %timeit factors( 10**1 ) 2 3 OUT:100000 loops, best of 3: 5.53 μs per loop 4 5 %timeit factors( 10**2 ) 6 7 OUT:100000 loops, best of 3: 8.03 μs per loop 8 9 %timeit factors( 10**3 ) 10 11 OUT:100000 loops, best of 3: 11.1 μs per loop 12 13 %timeit factors( 10**6 ) 14 15 OUT:100000 loops, best of 3: 133 μs per loop 16 17 %timeit factors( 10**10 ) 18 19 OUT:100000 loops, best of 3: 19.8 ms per loop
【引用】