【发布时间】:2023-03-03 16:37:02
【问题描述】:
我有两种不同的方法,一种是使用迭代计算斐波那契数列到 nth 元素,另一种是使用递归方法做同样的事情。
程序示例如下所示:
import java.util.Scanner;
public class recursionVsIteration {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
//nth element input
System.out.print("Enter the last element of Fibonacci sequence: ");
int n = sc.nextInt();
//Print out iteration method
System.out.println("Fibonacci iteration:");
long start = System.currentTimeMillis();
System.out.printf("Fibonacci sequence(element at index %d) = %d \n", n, fibIteration(n));
System.out.printf("Time: %d ms\n", System.currentTimeMillis() - start);
//Print out recursive method
System.out.println("Fibonacci recursion:");
start = System.currentTimeMillis();
System.out.printf("Fibonacci sequence(element at index %d) = %d \n", n, fibRecursion(n));
System.out.printf("Time: %d ms\n", System.currentTimeMillis() - start);
}
//Iteration method
static int fibIteration(int n) {
int x = 0, y = 1, z = 1;
for (int i = 0; i < n; i++) {
x = y;
y = z;
z = x + y;
}
return x;
}
//Recursive method
static int fibRecursion(int n) {
if ((n == 1) || (n == 0)) {
return n;
}
return fibRecursion(n - 1) + fibRecursion(n - 2);
}
}
我试图找出哪种方法更快。我得出的结论是,数字越少,递归越快,但是随着 nth 元素值的增加,递归变得更慢,迭代变得更快。以下是三种不同 n 的三种不同结果:
示例 #1(n = 10)
Enter the last element of Fibonacci sequence: 10
Fibonacci iteration:
Fibonacci sequence(element at index 10) = 55
Time: 5 ms
Fibonacci recursion:
Fibonacci sequence(element at index 10) = 55
Time: 0 ms
示例 #2(n = 20)
Enter the last element of Fibonacci sequence: 20
Fibonacci iteration:
Fibonacci sequence(element at index 20) = 6765
Time: 4 ms
Fibonacci recursion:
Fibonacci sequence(element at index 20) = 6765
Time: 2 ms
示例 #3(n = 30)
Enter the last element of Fibonacci sequence: 30
Fibonacci iteration:
Fibonacci sequence(element at index 30) = 832040
Time: 4 ms
Fibonacci recursion:
Fibonacci sequence(element at index 30) = 832040
Time: 15 ms
我真正想知道的是为什么突然迭代变得更快而递归变得更慢。如果我错过了这个问题的一些明显答案,我很抱歉,但我还是编程新手,我真的不明白背后发生了什么,我想知道。请提供一个很好的解释或指出正确的方向,以便我自己找出答案。另外,如果这不是测试哪种方法更快的好方法,请告诉我并建议我不同的方法。
提前致谢!
【问题讨论】:
-
递归调用函数会增加开销。
-
这两种方法不完全相同(甚至从图片中排除递归/迭代)
-
第一个问题:您的基准测试方法存在很大缺陷。您确实没有做足够的工作来准确测量差异。您应该使用
System.nanoTime,并重复调用几次,以便测量有用的工作量。接下来,查看每个调用的复杂性...计算出每种情况下完成了多少工作,随着 n 的增长。提示:尝试在纸上说明如果调用 fibRecursion(8) 与 fibIteration(8) 会发生什么。 -
最快的方法是closed form。
-
斐波那契数列的迭代、递归和记忆实现的一个很好的比较here