链接到问题:https://projecteuler.net/problem=14
所以我使用了一种相当“平凡”的 R 中的记忆化实现来解决这个问题。基本上,我只是从 1:1,000,000 开始计数,并计算得到 1 所需的 Collatz 应用次数。如果我遇到一个小于当前迭代的数字,则只需将该数字的“链”添加到当前序列中。
R 代码:
现在这段代码相对较快,即使对于R来说也是如此,但我越想这个问题,就越觉得它很有趣。
从空间和运行时间的效率方面来看,似乎有大量不同的方法可以处理它。也许倒序循环?也许先运行奇数或偶数,然后再运行另一半?也许在递增时保留中间结果而不仅仅是终端链长度?可能还有一些更加“数学”而不是直接与动态规划相关的想法。有没有人思考过这个问题/算法并能提供一些其他可能更有效的实现呢?
R 代码:
collatz <- function(n) {
if(n %% 2 == 0) return(n / 2)
else return(3 * n + 1)
}
chains <- rep(0, 1e6)
for(i in 1:length(chains)) {
n <- i
iter <- 0
while(n != 1) {
n <- collatz(n)
iter <- iter + 1
if(n < i) {
iter <- iter + chains[n]
break
}
}
chains[i] <- iter
}
which.max(chains)
现在这段代码相对较快,即使对于R来说也是如此,但我越想这个问题,就越觉得它很有趣。
从空间和运行时间的效率方面来看,似乎有大量不同的方法可以处理它。也许倒序循环?也许先运行奇数或偶数,然后再运行另一半?也许在递增时保留中间结果而不仅仅是终端链长度?可能还有一些更加“数学”而不是直接与动态规划相关的想法。有没有人思考过这个问题/算法并能提供一些其他可能更有效的实现呢?