[英]Memoization with recursive method in java
我正在做家庭作业,我已经筋疲力尽了。 我是编程新手,这是我的第一堂编程课。
这就是问题:
考虑 Collatz.java 中的以下递归函数,它与数论中一个著名的未解决问题有关,称为 Collatz 问题或 3n + 1 问题。
public static void collatz(int n) {
StdOut.print(n + " ");
if (n == 1) return;
if (n % 2 == 0) collatz(n / 2);
else collatz(3*n + 1);}
例如,调用 collatz(7) 会打印序列 7 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1 作为 17 次递归调用的结果。 编写一个程序,接受命令行参数 N 并返回 n < N 的值,此时 collatz(n) 的递归调用次数最大化。 提示:使用记忆。 未解决的问题是没有人知道函数是否对 n 的所有正值终止(数学归纳法没有帮助,因为递归调用之一是针对更大的参数值)。
我尝试了几件事:使用 for 循环,尝试使用每次执行方法时递增的变量来计算执行次数,以及繁重的工作时间。
显然,我应该在记忆中以某种方式使用数组。 但是,当必须在启动时指定数组的长度时,我不明白如何使用数组。
我做错了什么吗? 我误读了这个问题吗?
到目前为止,这是我的代码。 它反映了尝试创建整数数组的尝试:
public class Collatz2 {
public static int collatz2(int n)
{
StdOut.print(n + " ");
if (n==1) {return 1;}
else if (n==2) {return 1;}
else if (n%2==0) {return collatz2(n/2);}
else {return collatz2(3*n+1);}
}
public static void main(String[] args)
{
int N = Integer.parseInt(args[0]);
StdOut.println(collatz2(N));
}
}
编辑:
我写了一个单独的程序
public class Count {
public static void main(String[] args) {
int count = 0;
while (!StdIn.isEmpty()) {
int value = StdIn.readInt();
count++;
}
StdOut.println("count is " + count);
}
}
然后我使用了管道:%java Collatz2 6 | 计数
它工作得很好。
由于您对最大序列大小而不一定是序列本身感兴趣,因此最好让 collatz 返回序列的大小。
private static final Map<Integer,Integer> previousResults = new HashMap<>();
private static int collatz(int n) {
int result = 1;
if(previousResults.containsKey(n)) {
return previousResults.get(n);
} else {
if(n==1) result = 1;
else if(n%2==0) result += collatz(n/2);
else result += collatz(3*n + 1);
previousResults.put(n, result);
return result;
}
}
记忆是通过在 Map previousResults 中存储之前 n 值的序列大小来实现的。
您可以在 main 函数中查找最大值:
public static void main(String[] args) {
int N = Integer.parseInt(args[0]);
int maxn=0, maxSize=0;
for(int n=N; n>0; n--) {
int size = collatz(n);
if(size>maxSize) {
maxn = n;
maxSize = size;
}
}
System.out.println(maxn + " - " + maxSize);
}
这里的技巧是编写一个递归方法,其中参数是您想要“记忆”的值。 例如,这里有一个方法版本,它将返回达到 1 所需的步数(当然,它假设n
大于或等于 1):
public int countSteps(final int n)
{
return doCollatz(0, n);
}
public static int doCollatz(final int nrSteps, final int n)
{
if (n == 1)
return nrSteps;
final int next = n % 2 == 0 ? n / 2 : 3 * n + 1;
return doCollatz(nrSteps + 1, next);
}
如果你要记录不同的步骤,你会传递一个List<Integer>
作为参数和.add()
在你经历时传递给它,等等。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.