3n + 1更大整数的优化思路

时间:2016-11-05 15:45:47

标签: algorithm

我最近进入了Skiena和Revilla的“编程挑战”一书,当我看到3n + 1问题的解决方案时,我感到有些惊讶,这个问题简直就是强制性的。基本上它是一个生成数字列表的算法,如果是偶数则除以2并乘以3,如果是奇数则加1。直到达到n = 1为止,这是基本情况。现在的诀窍是找到整数i和j之间的列表的最大长度,对于这两个变量,问题的范围在1到1,000,000之间。所以我想知道一个程序在动态编程方面会有多高效(如果是这样)。基本上,程序将对第一个数字进行一次传递,i,找到总长度,然后检查数组中的每个单独的数字,并将相关长度存储在HashMap或其他字典数据类型中。

例如: 假设i = 22且j = 23

对于22:

22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1

这意味着在字典中,结构会存储 (22,16),(11,15),(34,14)等......直到(1,1)

现在为23:

23 70 35 106 53 160 80 40 ...

自40岁以来,它就在词典中 程序将获得23到80的长度,即7,并将其添加到先前存储的长度为40,这是9,导致总列表长度为16.当然程序将存储长度​​为23,70,35等......如果数字越大,它应该计算得越快。

那么以这种方式处理这样一个问题的意见是什么?

1 个答案:

答案 0 :(得分:0)

我尝试了两种方法并将它们提交给UVaOJ,蛮力解决方案得到了运行时间~0.3秒和dp解决方案~0.0s。当范围变长时(例如超过1e7元素),它变得非常慢。

我刚用数组(备忘录)能够记住前500万(SIZE)值:

int cycleLength(long long n)
{
    if(n < 1) //overflow
        return 0;
    if (n == 1)
        return 1;

    if (n < SIZE && memo[n] != 0)
        return memo[n];

    int res = 1 + cycleLength(n % 2 == 0 ? n / 2 : 3 * n + 1);

    if (n < SIZE)
        memo[n] = res;

    return res;
}