我有这个工作表问题,我只是看不出它是如何手工完成的。每个方法调用另外两个方法来运行,因此每个方法都会调用另外两个方法。我不知道如何跟踪它的任何一个。我不知道除了把它放到Eclipse中之外怎么会找到答案。
static int fun(int x) {
if(x < 1) {
return 1;
} else {
return x + fun(x-1) + fun(x-2);
}
}
public static void main(String[] args) {
System.out.println(fun(4));
}
答案 0 :(得分:0)
首先,“拆分递归”不是我之前遇到过的术语。 Google认为我正在询问如何使用递归实现split
函数;例如将字符串分成单词。
如果您在询问是否可以手动执行该计算(即fun(n)
计算n
的某些值,那么答案显然是肯定的。你只需要一张足够大的纸和一些耐心 1 。
如果你问是否有可能为fun(n)
提出一个“封闭形式”等式......我怀疑答案是肯定的。然而,这是一个数学问题而不是编程问题。 (基本上,你将fun
的声明映射到一个递归关系......并解决它。在这种情况下,它可能需要第一年的Uni数学技能。一旦你有封闭的形式,它将很容易证明通过归纳纠正。)
如果您询问是否有更快的程序来计算fun(n)
,那么答案是肯定的:
O(N)
解决方案。O(1)
解决方案。(我假设您可以使用int
或long
算术。)
1 - 实际上,对于足够大的N值,您应该能够使用铅笔和纸张(和智能)比运行该程序更快地计算fun(n)
。该程序具有复杂性(2^N)
...正如所写。
答案 1 :(得分:0)
更简单的解决方案:声明一个足够大的数组,使fun(4)
的值保持在您需要的值。在要求int[5]
时,您需要x + 1
。填写前两个元素的硬编码值,然后在循环中使用公式填充其余条目。现在你的结果在最后一个元素中。
可能的空间需求优化:通过循环的所有时间只需要最后两个和当前值,因此您无需将所有值存储在大小为['One', 'Two', 'Three']
的数组中。
答案 2 :(得分:0)
如果您指的是有时多次调用自己的函数,那么是!
基本案例:x < 1 ==> 1
,fun(-1)
以及fun(0)
代替1
fun(1) ; == [substitute default case with result]
1 + fun(0) + fun(-1); == [substitute base cases]
1 + 1 + 1 ; ==> 3
fun(2) ; == [substitute default case with result]
2 + fun(1) + fun(0) ; == [substitute fun(1) with previously calculated result]
2 + 3 + fun(0) ; == [substitute base cases]
2 + 3 + 1 ; ==> 6
fun(3) ; == [substitute default case with result]
3 + fun(2) + fun(1) ; == [substitute with previously calculated result]
3 + 6 + 3 ; ==> 12
fun(4) ; == [substitute default case with result]
4 + fun(3) + fun(2) ; == [substitute with previously calculated results]
4 + 12 + 6 ; ==> 22
你可以这样开始使用fun(4)
:
fun(4) ; == [expand default cases]
4 +
fun(3) +
fun(2) ; == [expand default cases]
4 +
3 + fun(2) + fun(1) +
2 + fun(1) + fun(0) ; == [expand fun(2) default case]
4 +
3 + (2 + fun(1) + fun(0)) + fun(1) +
2 + fun(1) + fun(0) ; == [group]
4 + 3 + 2*2 + 3*fun(1) + 2*fun(0) ; == [expand default cases]
4 + 3 + 2*2 + 2*fun(0) +
3*(1 + fun(0) + fun(-1)) ; == [group, group x<1 as b]
4 + 3+ 2*2 + 3*1 + 8*fun(b) ; == [expand base cases]
4 + 3+ 2*2 + 3*1 + 8*1 ; == [calculate]
; ==> 22
我觉得它有点乱。特别是如果你不将几个电话组合在一起,那可能会很痛苦。
请注意,如果函数结果未直接映射到其参数,则无法执行此操作。作为一种享受,这是一个更好的功能版本:
static int fun(int n) {
return fun(n, 0, 1, 3);
}
static int fun(int n, int v, int a, int b) {
return n >= v ? a : fun(n, v+1, b, a+b+n+2);
}
它似乎与序列A066982一致,只是省略了第一个元素。
答案 3 :(得分:0)
所以你想要的是系列的第n个项:Un = n + U(n-1)+ U(n-2)。
由于没有人提到它,这里是使用2个累加器的尾递归版本,你想要在OCaml中做什么:
let f x =
let rec f' acc' acc'' i =
if i = x then i+acc''
else f' (i+acc'') (i+acc'+acc'') (i+1)
in f' 1 1 0
如果您正在使用尾部优化的语言(如嗡嗡声......请说OCaml),它会超级快。既然你没有,这就是Java中悲伤,不优雅,命令式的版本:
public static int f (int x){
int acc1 = 1 ,acc2 = 1;
for (int i = 0; i<x; i++){
int tmp = acc1;
acc1 = i+acc2;
acc2 = i+tmp+acc2;
}
return x+acc2;
}
正如您所看到的,无需使用memoization或巨大的数组或类似的复杂事物。一个简单的for循环可以做到这一点:)。
您可以通过在循环体内打印(x + acc2)来获得所有中间结果