![](/img/trans.png)
[英]The fastest and most efficient way to get max number from a list of numbers
[英]Fastest and most compact way to get the smallest number that is divisible by numbers from 1 to n
我试图找到可被从 1 到 n 的数字整除的最小数字,现在我正在寻找有关如何进一步压缩/使我的解决方案更有效的建议。 如果也有 O(1) 的解决方案,那就太酷了。
def get_smallest_number(n):
"""
returns the smallest number that is divisible by numbers from 1 to n
"""
divisors = range(1, n+1)
check_divisible = lambda x: all([x % y == 0 for y in divisors])
i = 1
while True:
if check_divisible(i):
return i
i += 1
从数学上讲,您正在计算1, 2, ..., n
的最小公倍数。 lcm
很容易从gcd
派生出来,并且lcm
是一个关联操作。 reduce
可用于将关联操作应用于可交互对象。 我们可以结合这些想法(以及评论中 Mark Dickinson 和 Eric Postpischil 的改进)来获得一个非常快速的解决方案:
from math import gcd
from functools import reduce
def lcm(a,b):
return a // gcd(a,b) * b
def get_smallest_number2(n):
return reduce(lcm,range(1 + n//2,n+1),1)
IPython 中的一些快速%timeit
结果:
%timeit get_smallest_number2(15)
2.07 µs ± 26.5 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
%timeit get_smallest_number(15)
443 ms ± 5.75 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
对于n = 15
,它因此快 200,000 倍以上。 您的 function 早在n = 100
之前就无法产生任何 output ,但get_smallest_number2(100)
几乎立即计算为69720375229712477164533808935312303556800
。
首先考虑阶乘 n。这显然可以被所有小于 n 的数整除。 但不是这样的最小数字,例如,您可以将 n 除以 6。较小的结果仍可被 2 和 3 整除,因此仍可被 6 整除。
我们可以划分出哪些数字? 只要存在所有必需的素数,复合材料(如 6)就无关紧要:在这种情况下为 2 和 3。 素数免费为您提供复合材料。 所以,专注于素数。
从 2 开始。查看 2 的幂:2、4、8、16、... 遍历 2 的幂,直到找到小于或等于 n 的最高幂。 这是您需要的唯一 2 的幂,所有较低的幂都是不必要的。 如果 n 为 8 或更高,则不需要明确包含 4,因为这样您将拥有 8、16 或其他任何乘数。 重复 3 的幂:3, 9, 27, 81, ... 直到 sqrt(n) 的素数。 超过这一点,您只需要小于 n 的剩余素数,因为这些素数的更高幂将超过 n。
将选定的素数乘以得到最小的 n。
使用埃拉托色尼筛法生成初始素数列表,最多为 n。
实现 LCM 的另一种方法
import time
from datetime import timedelta
start_time = time.monotonic()
def lcm(nums):
res = 1
for i in nums:
res = (res * i) // gcd(res, i)
return res
def gcd(a, b):
while b:
a, b = b, a%b
return a
print(lcm([8, 9, 10, 11, 12, 13, 14, 15]))
end_time = time.monotonic()
print(f'Duration: {timedelta(seconds=end_time - start_time)}')
生产
360360
Duration: 0:00:00.000061
[Program finished]
这个想法是在每次迭代中添加最高分频器并从高到低检查。 像这样的东西:
n = int(input("n = "))
result = 0
while True:
result += n
for i in range(n, 1, -1):
if result % i != 0:
break
else:
break
print(result)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.