我最近进入了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等......如果数字越大,它应该计算得越快。
那么以这种方式处理这样一个问题的意见是什么?
答案 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;
}