自学算法之斐波那契数列

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_37014990/article/details/79936051

设斐波那契数列,求第N项的值:

{1, 1, 2, 3, 5, 8, 13, 21, 34...}

斐波那契数列规律:

从第3项开始,每一项都等于前两项之和,即:当前值 = 前一项值 + 前前一项的值

从前人总结的规律来看,解决无非两种,方案如下:

方案一,利用数学公式,即递归表达式:

F(n) = F(n-1) + F(n-2),(n>=2)

递归公式出来,代码就好写了,但要注意边界条件。

/**
 *
 * 算法:斐波那契数列
 */
public class Fibonacci {
	public static int fibonacci(int n){
		//参数检查
		if(n < 0) return -1;
		//n = 1, n = 2的情况
		if(n == 1 || n == 2) return 1;
		//递归
		return fibonacci(n - 1) + fibonacci(n - 2);
	}
	
	@SuppressWarnings("resource")
	public static void main(String[] args) {
System.out.println("请输入第n项:");
		Scanner in = new Scanner(System.in);
		int n = in.nextInt();
		int result = fibonacci(n);
System.out.println("第" + n + "项的值为:" + result);
	}
}

注意,递归求解斐波那契数列,存在极大问题,如果求第200项的值,时间就有点吓人,这不是一般计算机能承受的。

读者百度一波,就会知道使用递归求斐波那契,时间复杂度为指数阶的算法,所有很难受。

那么,我们可不可以改进一波呢?

且看,方案二:利用数组记录前两项的值,则只需要做一次加法就可以得到当前项。

public class Fibonacci {
	public static int fibonacci(int n){ 
		//参数检查
		if(n < 0) return -1;
		//声明一维数组
		int[] arr = new int[n];		
		//初始化
		arr[0] = 1; //第一项
		arr[1] = 1; //第二项
		//第三项开始,对应数组下标2
		for(int i = 2, len = arr.length; i < len; i++){
			arr[i] = arr[i - 1] + arr[i - 2];
		}
		return arr[n - 1];
	}
	@SuppressWarnings("resource")
	public static void main(String[] args) {
System.out.println("请输入第n项:");
		Scanner in = new Scanner(System.in);
		int n = in.nextInt();
		int result = fibonacci(n);
System.out.println("第" + n + "项的值为:" + result);
	}
}

很明显,为了降低时间复杂度,我们使用了一个额外数组。

额,没错。用空间换时间,的确是个好办法。

但是,我们再思考一波,既然我们只想得到第n项的斐波那契的值,那么我们是否可以使用迭代法?

我们只保存中间结果,便于进行下次的计算:

	public static int fibonacci(int n){
		//参数检查
		if(n < 0) return -1;
		int s1 = 1; //第一项
		int s2 = 2; //第二项
		for(int i = 3; i <= n; i++){
			s2 = s1 + s2; //辗转相加
			s1 = s2 - s1; //记录前一项
		}
		return s2;
	}

写到这里,方案3是推荐的方法。

好了,笔者只写到这里,如有错误,欢迎指正。

猜你喜欢

转载自blog.csdn.net/qq_37014990/article/details/79936051
今日推荐