我使用以下代码完成了项目Euler问题14:
def longest_Collatz_sequence():
"""
returns longest Collatz
sequence based on formula:
n --> n/2 (n is even)
n --> 3n + 1 (n is odd)
"""
bestSequence = []
lengthOfLongest = 0
longestSequence = []
for n in range(999999,1,-1):
while n != 1:
l = len(longestSequence)
if n % 2 == 0:
longestSequence.append(n)
n /= 2
elif n % 2 != 0:
longestSequence.append(n)
n = (n * 3) + 1
if longestSequence[-1] == 2 and lengthOfLongest < l:
lengthOfLongest = l
bestSequence = longestSequence[:]
bestSequence.append(1)
longestSequence = []
return bestSequence[0]
获得最长的Collatz大约需要39秒 数字序列从1000000到2。 我想知道我是否可以缓存任何值来加速我的代码,以及如何 如果longestSequence [-1] == 2从我的代码中移除而没有获得无限循环以及任何其他方式可以改进代码。
为正整数集定义了以下迭代序列:
n→n / 2(n是偶数) n→3n + 1(n为奇数)
使用上面的规则并从13开始,我们生成以下序列:
13→40→20→10→5→16→8→4→2→1 可以看出,该序列(从13开始并在1结束)包含10个项。虽然尚未证实(Collatz问题),但据认为所有起始数字都以1结束。
哪个起始编号低于一百万,产生最长的链?
注意:一旦链条启动,条款允许超过一百万。
答案 0 :(得分:2)
每次在序列中生成项目时,您还会为 项生成项目。例如,对于13,您会发现它生成10个项目。但是在这个过程中你还会发现40个产生了9个项目,20个产生了8个项目,10个产生了7个项目等等。你可以记住列表或字典中的信息,这样在做完13之后你就永远不必看40 ,20,10,5,16,4或2.
此外,当您生成以前没有见过的序列时,您可以查看此信息并将其用作快捷方式。对于13,你在看到13之前已经看过10,所以你只计算40,20,10然后你知道10个产生7个项目所以你只需将它添加到你已经看过的3个并且不用费心计算其余部分。
这将使用相当多的内存,但它对于您必须考虑的项目数量是完全可行的。您可以使用某种截止值(例如,仅存储100,000或以下数据的结果),这仍然可以实现极快的速度提升但使用更少的内存。
这样做的简单方法是重写函数以递归计算序列而不是迭代,然后应用memoization装饰器,如this one。在递归中有一些开销,但是memoization的好处可能会超过这个。