我正在尝试解决下面详述的投射难题。我当前的函数适用于数字1到10,但是当我尝试1到20时,它只是永远循环而没有结果。
2520是可以除以1至10中的每个数字而没有任何余数的最小数字。 可以被1到20的所有数字整除的最小正数是多少?
def calculate():
results = dict()
target = 20
num_to_test = 1
while len(results) < target:
for j in range(1, target+1):
results[num_to_test] = True
if num_to_test % j != 0:
# current num_to_test failed in the 1-10, move on
del results[num_to_test]
break
num_to_test += 1
return min(results)
任何人都可以在逻辑中看到任何问题,特别是我想知道为什么它适用于10的目标,但不是20.谢谢
答案 0 :(得分:5)
你的算法效率很低,但你问题的核心是你的results
字典为每个整数积累了1个值,它们可以被1-20的数字整除,并且你的{{ 1}}循环试图继续前进,直到它有20个这样的数字。
这是实现这种低效算法的一种正确方法:
while
请注意,def calculate():
target = 20
candidate = 1
success = False
divisors = range(1, target+1)
while not success:
for divisor in divisors:
if candidate % divisor != 0:
candidate += 1
break
else:
success = True
return candidate
子句实际上是for循环,而不是if。来自流量控制的tutorial:
循环语句可能有一个else子句;当循环通过列表耗尽(with for)或条件变为false(with while)时终止,但是当循环被break语句终止时,执行它。
更简洁的表达方式是:
else
它使用生成器表达式,因此candidate = 0
while not success:
candidate += 1
success = all((candidate % divisor == 0 for divisor in divisors))
可以短路并避免进行不必要的计算。
由于这是一个难题,我将继续提出更好的算法。
答案 1 :(得分:4)
实际上我对这个问题有非常有效的算法。 我不会给你代码,但我可以告诉你的方式
对于N = 10
1.计算从5到10的所有数字的所有因素:
[[2, 3], [7], [2, 2, 2], [3, 3], [2, 5]]
2.计算列表中每个素数的最大数量
{2: 3, 3: 2, 5: 1, 7: 1}
3.确定关键功率值的乘积
2^3 * 3^2 * 5 * 7 = 2520
答案 2 :(得分:2)
许多其他答案都提到原始代码效率低下,但它们仍然会遍历几乎所有数字。利用lcm函数不是更有效吗?
def calculate(num, current_lcm = 1):
if (num == 1): return current_lcm
return calculate(num - 1, lcm(num, current_lcm))
def lcm(a, b):
return a * b // gcd(a, b)
def gcd(a, b):
while b:
a, b = b, a % b
return a
print calculate(20)
答案 3 :(得分:1)
不要存储所有内容,而只是在找到它时尽早返回,去掉那个结果字典,顺便说一下这根本不是最优的,只是一个清理
def calculate():
target = 20
num_to_test = 0
while True:
num_to_test += target
if all((num_to_test % j == 0) for j in range(1,target+1)):
return num_to_test
return -1
此外,您不需要测试不是最大倍数的数字。它的运行速度要快20倍。
我转而使用生成器进行测试,以查看该数字是否可以被all()
的nubmers从1到20整除
用于编写自己的算法而不复制一个算法的道具:)
答案 4 :(得分:1)
虽然您的算法效率非常低,但这可能有助于实现这一小改变
if num_to_test % j = 0:
results[num_to_test] = True
else:
# current num_to_test failed in the 1-10, move on
break
不确定为什么要存放它们?也许是为了调试?
提示。最好计算结果的素因子并简单地将它们相乘。
# spoiler
def calculate(target):
n = 1
for i in range(1, target+1):
for j in range(1, target+1):
if (n * j) % i == 0:
n *= j
break
return n