斐波那契数列公式:
F(0) = 0,F(1) = 1,F(n) = F(n - 1) + F(n - 2).
解法一:
package demo;
import java.util.Scanner;
public class Fibonacci {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println("请输入数字:");
int num = scan.nextInt();
System.out.printf("F(%d) = %d", num ,fibonacci(num));
}
public static long fibonacci(int num) {
if (num == 0) {
return 0;
} else if (num == 1) {
return 1;
} else {
return (fibonacci(num - 1) + fibonacci(num - 2));
}
}
}
这种简单的递归方法在计算较大的斐波那契数时效率非常低,因为它进行了大量的重复计算。例如,为了计算 fibonacci(n),它会两次计算 fibonacci(n - 1),而计算 fibonacci(n - 1) 时又会两次计算 fibonacci(n - 2),以此类推。这种重复计算导致了指数级的时间复杂度。
为了避免这种重复计算,可以使用记忆化递归或动态规划来提高效率。记忆化递归在递归调用中存储已经计算过的值,以避免重复计算。而动态规划则通过迭代的方式来计算斐波那契数列的值,通常更加高效。
解法二:使用记忆化递归(也称为带缓存的递归)来编写斐波那契数列:
public class Fibonacci {
private static long[] memo;
public static void main(String[] args) {
int n = 10; // 你可以改变这个值来计算斐波那契数列中的不同项
long fibValue = fibonacci(n);
System.out.println("F(" + n + ") = " + fibValue);
}
public static long fibonacci(int n) {
if (memo == null || memo.length <= n) {
// 扩展缓存数组以包含更多的斐波那契数
memo = new long[n + 1];
}
if (memo[n] != 0) {
// 如果已经计算过,直接返回结果
return memo[n];
}
if (n <= 1) {
// 斐波那契数列的前两个数
memo[n] = n;
} else {
// 递归计算斐波那契数,并存储结果
memo[n] = fibonacci(n - 1) + fibonacci(n - 2);
}
return memo[n];
}
}
在这个例子中,我们定义了一个静态的 long 数组 memo 来存储已经计算过的斐波那契数。每次调用 fibonacci 方法时,我们首先检查 memo 数组是否已经初始化,并且是否包含我们需要的斐波那契数。如果 memo 数组为空或者长度不够,我们就扩展它。然后,我们检查 memo[n] 是否已经计算过(即是否不为0),如果是,则直接返回存储的值。否则,我们递归地计算 fibonacci(n - 1) 和 fibonacci(n - 2),并将它们的和存储在 memo[n] 中,以便将来使用。
解法三:使用动态规划计算斐波那契数列
public class Fibonacci {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println("请输入数字:");
int num = scan.nextInt();
long[] fibArray = new long[num + 1];
fibArray[0] = 0;
if (num >= 1) {
fibArray[1] = 1;
}
for (int i = 2; i <= num; i++) {
fibArray[i] = fibArray[i - 1] + fibArray[i - 2];
}
System.out.println("F(" + num + ") = " + fibArray[num]);
}
}
在这个例子中,我们创建了一个数组 fibArray 来存储斐波那契数列的值,并使用一个循环来计算它们。这种方法避免了递归中的重复计算,因此更加高效。