题目描述:
求斐波那契数列中的第n个值
斐波那契数列:{1, 1, 2, 3, 5, 8, 13, 21…}
输入:n — 你想要求的数
分析:
- 当 n == 1时, fib(n) = 1
- 当 n == 2时, fib(n) = 1
- 当 n > 2 时, fib(n) = fib(n - 1) + fib(n - 2)
递归法:
public class FeiBoNaQieShuLie {
private static int[] fib;
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n = input.nextInt();// 从 0 开始输入几就输出第几个数的值
fib = new int[n+1]; // 要想输入n就输出n对应的值,就需要数组设置的长度为n+ 1,从0开始
System.out.println(fibonacco(n)); // 调用方法并输出值
}
public static int fibonacco(int n) {
if(n == 1) return 1;
if(n == 2) return 1;
return fibonacco(n-1) + fibonacco(n-2);
}
}
如果数值比较大时,会出现多次重复计算,时间复杂度达到O(2n)。
例如: fib[4] = fib[3] + fib[2] = fib[2] + fib[1] + fib[2] ;
动态规划:自底向上法
时间复杂度:O(n), 空间复杂度O(n)
// 自底向上的方法: 从输入的最小参数值开始,逐步构建更大的参数值的解
public class FeiBoNaQieShuLie2 {
private static int[] fib;
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n = input.nextInt();// 从 0 开始输入几就输出第几个数的值
fib = new int[n+1]; // 要想输入n就输出n对应的值,就需要数组设置的长度为n+ 1,从0开始
System.out.println(fib(n)); // 调用方法并输出值
}
public static int fib(int n) {
if(n == 1 ) return 1;
if (n == 2) return 1;
// 最后两个是设定好的
fib[1] = 1;
fib[2] = 1;
// 求出第n个的值
for(int i = 3; i <= n; i++) {
fib[i] = fib[i-1] + fib[i-2];
}
// 返回第n个的值
return fib[n];
}
}
动态规划:自顶向下法
时间复杂度:O(n), 空间复杂度O(n)
// 自顶向下:保留递归调用,如果某个子问题的解已经求过,就直接使用这个值,增加备忘录
public class FeiBoNaQieShuLie3 {
private static int[] fib;
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n = input.nextInt();// 从 0 开始输入几就输出第几个数的值
fib = new int[n+1]; // 要想输入n就输出n对应的值,就需要数组设置的长度为n+ 1,从0开始
System.out.println(fibonacco(n)); // 调用方法并输出值
}
public static int fibonacco(int n) {
if(n == 1) return 1;
if(n == 2) return 1;
if (fib[n] != 0) {
return fib[n];
}
return fib[n] = fibonacco(n-1) + fibonacco(n-2);
}
}
最强算法:
因为每次只用到了最后两个的值,所以只需要保存最后两个的值即可
时间复杂度O(n), 空间复杂度O(1)
public static int fibonacco(int n) {
if(n == 1) return 1;
if(n == 2) return 1;
int sum = 2, a = 1, b = 1;
for (int i = 3; i <= n; i++) {
sum = a + b;
a = b;
b = sum;
}
return sum;
}