未检查定理(Collatz):应用这个函数序列的所有数字,都以1结尾。在1到1000000之间的数字中,哪个对应最长的序列?你知道吗
我怎样才能使用memoization,这样操作就不会花费那么长时间,并且知道从1到1000000的最大序列?你知道吗
def Collatz(n, arr):
arr.append(n)
if n == 1:
return arr
elif n % 2 == 0:
return Collatz(n / 2, arr)
elif n % 2 == 1:
return Collatz((3 * n) + 1, arr)
Memoization提供了一个来自 输入到输出是一种避免重复计算的快捷方式。为了 collatz,输入是一个整数
n
注意arr
并不是输入的一部分。你知道吗既然你想找到最长的序列,那么让 映射应该是从
n
到列表的那种序列arr
,你的原始 代码返回。(下面是一个更快的方法,它证明了记忆只是 序列的长度要快得多。)尽管如此,让我们继续保持最初的想法,看看您的代码在记忆化时会是什么样子: 用于记忆的dict应该有键,它们是整数,
n
,和值,它们是类似arr
的列表:马上处理回忆录。如果
n
在dictseen
中, 我们可以跳过if-statement
的主体,只返回seen[n]
。你知道吗我选择将
return seen[n]
放在末尾,这样就非常清楚 对collatz
的所有调用都在此return语句处结束。处理好基本情况。
注意,如果
collatz
总是为某些n
返回seen[n]
,如果seen[n]
总是一个列表,那么collatz(n // 2, seen) + [n]
将是collatz
返回的列表,并且n
附加在列表的末尾。(例如,在Python中[1] + [2]
是[1, 2]
)。退货
计算大约需要24秒(在我的电脑上)。你知道吗
更快的方法:
改进此代码的一种可能方法是减少代码中的重复量
seen
。这张单子可能会占用很多内存,因为有很多 键和列表可能会变得很长。此外,还有很多重复 在列表中。你知道吗如果我们只保留序列的长度,而不是序列本身呢? 即使我们想找到最长的序列, 一旦我们知道了与最长序列相关的
n
,就可以很快地重新生成序列。你知道吗现在代码如下所示:
现在
seen
是从值n
到序列整数长度的映射。 与最长序列相关的n
值现在可以通过以下方式找到:运行这个版本的代码需要24秒,而不是2秒
最后,有两个版本的代码(
collatz
和show_collatz
)做几乎相同的事情违反了DRY principle(不要重复你自己)。我们可以通过添加一个参数return_length
来处理这两种情况来解决这个问题。令人高兴的是,这两个函数的相似性很强,变化很小:相关问题 更多 >
编程相关推荐