项目Euler#14:Collat​​z猜想 - 有效利用记忆/速度的算法是什么?

时间:2015-07-10 22:16:46

标签: algorithm performance big-o dynamic-programming memoization

问题链接:https://projecteuler.net/problem=14

所以我在R中使用相当“琐碎”的memoization实现解决了这个问题。基本上,我只需要从1:1,000,000计算并计算到达1所需的collat​​z应用程序数量。如果我遇到了如果数字小于当前迭代次数,我只需将该数字的“链”添加到当前序列中。

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,但是我对这个问题的思考越多,我发现它就越有趣。

似乎有很多不同的方法可以在空间和运行时方面提高效率。也许循环倒退?也许首先通过奇数或偶数,然后再做另一半?也许保持中间结果而不仅仅是递增时的终端链长度?可能还有一些想法本质上更“数学”而不是直接与动态规划相关。有没有人考虑过这个问题/算法,并且可以提供其他一些可能更有效的实现?

1 个答案:

答案 0 :(得分:6)

您正在以严格的1:1000000顺序进行记忆。但是,没有理由在第一次看到值时不记忆。例如,从3开始给出序列3 -> 10 -> 5 -> 16 -> 8 -> 4 -> 2 -> 1。除了记住10, 5, 16, 8, 4之外,您还可以记住3

这可能会大幅减少操作次数。继续上面的示例,在您第一次看到它时记忆4保存了稍后要记住它的2个步骤,并且记住5又保存了3个步骤。似乎这些保存的步骤应该很快滚雪球。