斐波那契数列的几种解法

斐波那契数列定义:

斐波那契数列指的是这样一个数列 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,377,610,987........数组

这个数列从第3项开始,每一项都等于前两项之和。缓存

1.常规解法---递归

根据第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

2.递归+全局数组

因为第一种方式重复计算的次数过多,为了不咱们能够创建一个相似于全局变量的数组来存储已经计算出来的数列项,在每一次递归时直接取出来前两个值,省去重复计算。代码以下: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

3.循环实现

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)(建立了四个对象,是常数,因此可忽略不计)对象

4.斐波那契通项公式

斐波那契还存在一个通项公式: 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);
	}
}
复制代码
相关文章
相关标签/搜索