斐波那契数列指的是这样一个数列 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,377,610,987........数组
这个数列从第3项开始,每一项都等于前两项之和。缓存
根据第n项的值等于n-1和n-2的值之和这个特性,代码以下:bash
public class Fibonacci {
public static int Fib(int N) {
if (N < 3)
return 1;
else
return Fib(N - 1) + Fib(N - 2);
}
public static void main(String[] args) {
int num = Fib(10);
System.out.println(num);
}
}
复制代码
这种方法的最大缺陷就是重复计算的次数太多了,致使时间复杂度高
,好比当n=3时ui
1. Fib1(3)=Fib1(2)+Fib1(1)
2. 计算Fib1(1) 第一次计算
3. 计算Fib1(2) 第二次计算
4. 计算Fib1(2)+Fib1(1) 第三次计算
复制代码
就须要计算三次,时间复杂度:O(2^N),空间复杂度:O(N)spa
因为第一种方式重复计算的次数过多,为了不咱们能够创建一个相似于全局变量的数组来存储已经计算出来的数列项,在每一次递归时直接取出来前两个值,省去重复计算。代码以下:code
public class FibArray {
public static int[] array = new int[20];
public static int Fib(int n) {
if (n <= 1)
return n;
if (array[n] != 0)
return array[n];
else
return array[n] = Fib(n - 1) + Fib(n - 2);
}
public static void main(String[] args) {
int num = Fib(10);
System.out.println(num);
}
}
复制代码
此种方法至关于缓存了前面的值,很大程度的减少了第一种方法(递归实现斐波那契数列)的时间复杂度,缺点是须要另外开辟数组内存,数组的长度是固定的,不能动态调整。
时间复杂度:0(N), 空间复杂度:0(N)cdn
public class FibForEach {
public static int Fib(int n) {
int first = 1;
int second = 1;
int ret = 0;
for (int i = 3; i <= n; i++) {
ret = first + second;
first = second;
second = ret;
}
return second;
}
public static void main(String[] args) {
int num = Fib(10);
System.out.println(num);
}
}
复制代码
循环的方式省去了数组这个不定的因素,优势:时间复杂度和空间复杂度最低,并且可读性高
时间复杂度:O(N)
空间复杂度:O(1)(建立了四个对象,是常数,因此可忽略不计)对象
斐波那契还存在一个通项公式: blog
public class FibAll {
static double ROOT_OF_FIVE = Math.sqrt(5.0);
static double Fib(int n) {
return (Math.pow(((1 + ROOT_OF_FIVE) / 2.0), n) / ROOT_OF_FIVE
- Math.pow(((1 - ROOT_OF_FIVE) / 2.0), n) / ROOT_OF_FIVE);
}
public static void main(String[] args) {
double num = Fib(10);
System.out.println(num);
}
}
复制代码