以下是代码:
class qual
{
public static int fibonacci(int n)
{
if (n == 0 || n == 1)
{
return 1;
}
else
{
return fibonacci(n-1) + fibonacci(n-2);
}
}
public static void main(String[] arg)
{
System.out.println(fibonacci(5));
}
}
输出为8。
输出应该是8,但是当我看到它时,我认为它应该是7((5-1) +(5-2)
)。
为什么输出8?我认为获得8后面的推理会使递归可能不再让我感到困惑。
答案 0 :(得分:20)
让我们将其视为代数,我会写f(n)
代替fibonacci(n)
来节省空间:
f(5) = f(4) + f(3)
f(5) = f(3) + f(2) + f(2) + f(1)
f(5) = f(2) + f(1) + f(1) + f(0) + f(1) + f(0) + f(1)
f(5) = f(1) + f(0) + f(1) + f(1) + f(0) + f(1) + f(0) + f(1)
f(5) = 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1
答案 1 :(得分:19)
因为它是一个递归调用,所以参数不是0或1的每次调用都会再次调用它。
fibonacci(7)
-> fibonacci(6) // recursively calls itself with (7-1)
-> fibonacci(5) // recursively calls itself with (6-1)
-> fibonacci(4) // recursively calls itself with (5-1)
-> fibonacci(3) // recursively calls itself with (4-1)
-> fibonacci(2) // recursively calls itself with (3-1)
-> fibonacci(1) // recursively calls itself with (2-1)
-> fibonacci(4) // recursively calls itself with (6-2)
...
-> fibonacci(5) // recursively calls itself with (7-2)
-> fibonacci(4) // recursively calls itself with (5-1)
-> fibonacci(3) // recursively calls itself with (4-1)
-> fibonacci(2) // recursively calls itself with (3-1)
-> fibonacci(1) // recursively calls itself with (2-1)
-> fibonacci(3) // recursively calls itself with (5-2)
...
等等。
考虑这样的逻辑,你应该能够找出实际返回初始调用者的内容。
答案 2 :(得分:7)
它正在返回fibonacci(n-1)
,而不是n-1
。当你用5调用它时,你会得到:
return fib(4) + fib(3);
fib(4)返回:
return fib(3) + fib(2);
fib(3)返回:
return fib(2) + fib(1);
fib(2)返回:
return fib(1) + fib(0);
一旦达到fib(1)或fib(0),就返回1;
向后工作,fib(2)
返回2:
return 1 /*fib(1)*/ + 1 /*fib(0)*/;
按照相同的逻辑,fib(3)
返回2 + 1
或3. Fib(4)
返回3 + 2
,或5. Fib(5)
返回5 + 3
,这是你的8。
答案 3 :(得分:5)
也许这个改编自Structure and Interpretation of Computer Programs(SICP或向导书)的插图会有所帮助:
alt text http://img58.imageshack.us/img58/8575/fib5.gif
关于切线,SICP虽然有时难以介绍编程,但却非常深刻。由于它使用Lisp(而不是Scheme)作为其教学语言,因此始终使用递归。即使Lisp中的迭代过程也基于递归调用:
(define (factorial n)
(define (fact-iter n product)
(if (> n 1)
(fact-iter (- n 1) (* product n))
product
) )
(fact-iter n 1)
)
(factorial 5)
; returns 120
实际上是iterative。注意:car
返回列表的头部,而cdr
返回尾部。运营商使用prefix notation; (- a b)
是“a - b”,(* a b)
是“a * b”。
以下是您的Fibonacci计划在Scheme中的样子:
(define (fibonacci n)
(if (or (= n 1) (= n 2))
1
(+ (fibonacci (- n 1)) (fibonacci (- n 2)))
)
答案 4 :(得分:4)
不是((5-1) + (5-2))
,而是(finonacci(5-1) + fibonacci(5-2))
finonacci(5-1)
缩小为fibonacci(4)
,后者变为(finonacci(4-1) + fibonacci(4-2))
等。
答案 5 :(得分:3)
return fibonacci (n-1) + fibonacci (n-2);
这实际上不只是做(n-1)+(n-2),而是递归地再次调用fibonnacci函数。
所以它正在做斐波那契(4)+斐波那契(3)。然后评估fib(4)为fib(3)+ fib(2),因此它最终返回fib(3)+ fib(2)+ fib(3)。同样,那些fib(3)中的每一个实际上是fib(2)+ fib(1),依此类推。它一直在崩溃,直到碰到
if (n == 0 || n == 1)
所以它最终变成了一堆fib(1)+ fib(0)+ fib(1)...,这是1 + 1 + 1 ......,如果你实际破坏它将最终为8它一路下来。
答案 6 :(得分:3)
我还没有看到这种方法。想象一下,您正在存储结果并进行构建,其中f[i]
是调用fibonacci(i)
的结果。 0和1是基本情况,其余的基于它:
f[0] = 1
f[1] = 1
f[2] = f[1] + f[0] = 1 + 1 = 2
f[3] = f[2] + f[1] = 2 + 1 = 3
f[4] = f[3] + f[2] = 3 + 2 = 5
f[5] = f[4] + f[3] = 5 + 3 = 8
答案 7 :(得分:2)
该函数的结果不是(5 - 1) + (5 - 2)
,而是fibonacci( 5 - 1 ) + fibonacci( 5 - 2 )
或fibonacci( 4 ) + fibonacci( 3 )
,即5 + 3.序列为:
1 1 2 3 5 8
0 1 2 3 4 5
答案 8 :(得分:2)
Recursion实际上与proof by induction的数学概念密切相关 - 实际上Fibonacci序列是递归定义的,所以在某种程度上你必须用递归术语来思考它是如何理解的的工作原理。
为了更好地理解代码,您可以应用beta reduction - 也就是说,将每个函数调用替换为函数本身。
如果fibonacci(n)
转换为fibonacci(n - 1) + fibonacci(n - 2)
,则:
fibonacci(5) = fibonacci(4) + fibonacci(3)
fibonacci(5) = (fibonacci(3) + fibonacci(2)) + (fibonacci(2) + fibonacci(1))
除非我们提出特殊情况,否则很容易看到这种情况会永远持续下去。在此,我们知道fibonacci(1)
会转换为1
,而fibonacci(0)
也会转换为1
。所以我们保持beta减少,直到我们剩下的都是那些,看起来像:
fibonacci(5) = ((1 + 1) + (1 + (1 + 1))) + ((1 + 1) + 1)
因此:
fibonacci(5) = 8
答案 9 :(得分:-1)
第一个斐波那契数是1,1,2,3,5,8,......任何其他数字都是出乎意料的。