1. 什么叫斐波那契数
1.1
形如:0,1,1,2,3,5,8,13。后面一个数等于前两数之和。
2. 题目描述
2.1
大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0)。
n<=39
3.解法1——递归
3.1 代码
public int Fibonacci(int n) {
if(n == 0)
return 0;
if(n == 1)
return 1;
return Fibonacci(n - 1) + Fibonacci(n - 2);
}
3.2 分析
代码解读:
- 采用递归的方法,调用自身返回。Java中每个线程都有自己的方法栈,从一开始的Fibonacci方法调用,依次将后面的方法调用入栈。直到n == 0,或者n == 1。然后方法栈里的方法出栈,并将结果返回到每个方法里。最后出栈的方法(也就是第一次调用)返回最终的结果。
复杂度解读:
可以看到,如果n为5,那么整个递归快进行了2的5次方次,时间复杂度约为O(n的平方)。我们知道2的次方越到后面越庞大。所以此算法效率低下。
4. 解法2——动态规划
4.1 代码
public int Fibonacci(int n) {
if(n == 0)
return 0;
if(n == 1)
return 1;
int[] dp = new int[40];
dp[0] = 0;
dp[1] = 1;
for(int i = 2; i <= n; i++){
dp[i] = dp[i - 1] + dp[i - 2];
}
return dp[n];
}
4.2 分析
代码解读:
- 采用动态规划的思想。用一个数组来保存中间结果,然后循环计算得到最终结果。
复杂度解读:
- 代码中只循环了n次,所以关键操作也只执行了n此,时间复杂度为O(n)。
5. 解法3——迭代
5.1 代码
public int Fibonacci(int n) {
if(n == 0)
return 0;
if(n == 1)
return 1;
int result = 0;
int before = 0;
int after = 1;
for(int i = 0; i < n - 1; i++){ //注意,只循环n - 1次
result = before + after;
before = after;
after = result;
}
return result;
}
5.2 分析
代码解读:
- 采用迭代的思想。只用3个变量保存结果,依次迭代,得到最终结果。
复杂度解读:
- 代码中也循环了n次,所以关键操作也只执行了n此,时间复杂度为O(n)。但空间复杂度比解法2要好很多(试想一下,如果解法2n是二维数组,n更大呢?)。
6 总结
迭代和dp(动态规划)在时间上都优于递归,迭代在空间上优于dp。