我GitHub上的:剑指offer题解
题目描述:大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项。n<=39
斐波那契数列(Fibonacci sequence),又称黄金分割数列、因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:1、1、2、3、5、8、13、21、34、……在数学上,斐波纳契数列以如下被以递归的方法定义:F(0)=1,F(1)=1, F(n)=F(n-1)+F(n-2)(n>2,n∈N*)(来源百度百科)
思路:由于数组下标是从0开始的,但是我们是看第几个的,所以我们设第0项的值为0,第1项为1。
上述递归的解法有很严重的效率问题,通过求解第10项的调用过程图来分析:
从上图中不难发现:在这棵树中有很多结点是重复的,而且重复的结点数会随着n的增大而急剧增加,这意味计算量会随着n的增大而急剧增大。事实上,用递归方法计算的时间复杂度是以n的指数的方式递增的。
时间复杂度:O(2^n)
改进的方法并不复杂。上述递归代码之所以慢是因为重复的计算太多,我们只要想办法避免重复计算就行了
输入n,那么我们就计算到F(n-1)(即第n个),n是不确定的,所以用到动态数组ArrayList。
public static int Fibonacci(int n) { List<Integer> arr = new ArrayList<Integer>(); arr.add(0); arr.add(1); if (n <= 0 || n == 1) { return arr.get(n); } for(int i = 2; i <= n; i++){ arr.add(arr.get(i-1)+ arr.get(i-2)); } return arr.get(n); }时间复杂度:O(n)
空间复杂度:O(n)
如果不用ArrayList
public static int Fibonacci(int n) { if (n <= 0) { return 0; } if (n == 1) { return 1; } int currOne = 0; int currTwo = 1; int result = 0; for (int i = 2; i <= n; i++) { result = currOne + currTwo; currOne = currTwo; currTwo = result; } return result; }时间复杂度:O(n)
空间复杂度:O(1)
测试函数:
public static void main(String[] args) { int n = 3; int result = Fibonacci(n); System.out.println(result); }
如果考虑到n越来越大,那就要用到long的数据类型。
斐波那契数列的应用:
1.跳台阶+变态跳台阶
2.覆盖矩形
