1.原理和定义
斐波那契数列(Fibonacci sequence),又称黄金分割数列,因数学家莱昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为 “兔子数列”。
如下图所示,就是一个斐波那契数列:
在数学上,斐波那契数列被以如下递推的方法定义:
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/672049b7212f1587124660a3bc019692.png)
从斐波那契的递推公式我们可以总结出重要一点:斐波那契数列从第三项开始,每一项都等于前两项之和。
2. 递推方式实现斐波那契数列
public class FibonacciImp_3 {
//最简单的循环递推相加法
public static int getFibonacci(int n){
int a=1, b=1, c=0;
if(n==0) return 0;
if(n==1 || n==2) return 1;
// n>2 时, 我们利用a,b,c 的递推得出需要的斐波那契数
// 由于第一次我们从 c = a+b = 2开始的, n>2的斐波那契数我们需要递推(连加)n-2次
//例如: F(4)-->
/**
* 第一次: c=a+b=2,a=1,b=2 f3
* 第二次: c=a+b=3,a=2,b=3 f4
* 第三次: c=a+b=5,a=3,b=5 f5
* 第四次: c=a+b=8,a=5,b=8 f6
*/
for(int i=0; i<n-2; i++){
c = a+b;
a = b; // a,b后移
b = c;
}
return c;
}
public static void main(String[] args) {
for(int i=0; i<=20; i++){
System.out.println("斐波那契数: F("+i+")= "+getFibonacci(i));
}
}
3. 数组方式实现斐波那契数列
public class FibonacciImp {
/**
* 使用数组实现斐波那契
*/
public static int[] getFibonacci(int maxSize){
int[] fib = new int[maxSize+1];
//因为我们用给定的f(n)中的n+1去初始化数组
// 所以n=0,或是n=1会发生数组的越界
// 所以我们需要做以下处理
if(fib.length >= 1) fib[0] = 0;
if(fib.length >= 2 ) fib[1] = 1;
//注意, 斐波那契f(10)为数列的第11个数, 数列此时的长度为11
for(int i=2; i<= fib.length-1; i++){
fib[i] = fib[i-1] + fib[i-2];
}
return fib;
}
public static void main(String[] args) {
System.out.println(Arrays.toString(getFibonacci(20)));
}
}
4. 递归方式实现斐波那契数列
public class FibonacciImp_1 {
/**
* 递归实现斐波那契
*/
public static int getFibonacci(int n){
//起始的两个值
if(n==0) return 0;
if( n==1 || n==2) return 1;
//递归
if( n>2 )
return getFibonacci(n-1)+getFibonacci(n-2);
//递归出口
return -1;// n的值不为1,2,或者大于2
}
public static void main(String[] args) {
for(int i=0; i<=50; i++){
System.out.println("斐波那契数: F("+i+")= "+getFibonacci(i));
}
}
}
递归的实现方法最简单,也是很容易就能想到的。但是效率太低了,当n>=40时,你会发现计算时间明显变长,当n接近50时,idea运行窗口等了半天才反应过来。
注意:由于int的取值范围有限,最大值为 (2^32)-1 = 2147483647,当n>46的时候,会发生取值范围溢出的情况,所以这里如果想要验证n>46时的计算耗时情况,请将返回值类型int改为long。