菲波那切数列(Java)

这篇博客讨论了如何使用递归和循环来实现斐波那契数列的第n项。虽然递归实现简洁,但存在性能问题和可能导致栈溢出的风险。通过优化,可以用循环将时间复杂度降低到O(n),并提到存在基于矩阵公式的方法可进一步优化至O(logn)。博客强调理解递归的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:

写一个函数,输入n,求斐波那契(Fibonacci)数列的第n项。斐波那契数列的定义如下:


知识点:

递归:是在一个函数的内部调用这个函数自身。循环:则是通过设置计算的初始值及终止条件,在一个范围内重复运算。

通常基于递归实现的代码比基于循环实现的代码要简介很多,更加容易实现。如果面试官没有特殊要求,应优先采用递归的实现方法。

递归虽然简介明了,但是缺点很明显:递归是函数自身调用自身,而函数调用是有时间和空间的消耗的:每一次函数调用,都需要在内存栈中分配空间以保存参数、返回地址及临时变量,而且往栈里压入数据和弹出数据是需要时间。递归有可能很多计算都是重复的,从而对性能带来很大的负面影响。递归的本质是把一个问题分解成两个或多个小问题。如果多个小问题存在重叠的部分,,那么就存在重复的计算。斐波那契数列就是一个例子。

递归还可能引起调用栈溢出。因为递归每调用一次就在栈内存中分配空间,每个进程的栈容量都是有限的,故当递归调用的层级太多时,就会超出栈的容量,从而导致栈溢出。

第一思想:

求斐波那契数列第n项,是在我们课本上以讲解递归的例子出现的。故第一思想就是用递归实现。

递归代码:

//递归实现
public long fibonacci(int n){
	if(n <= 0){
		return 0;
	}
	if(n == 1){
		return 1;
	}
	return fibonacci(n - 1) + fibonacci(n - 2);
}

优化思想:

上面用递归实现的斐波那契数列时间复杂度为n的指数,在我们传入的n为100时,计算机计算结果都需要等很长一段时间,再大时计算机直接崩溃。因此我们可以考虑用循环去代替递归。递归是由第n项去求第n-1项以此类推在遇到n=1或者n=0时再反过来计算即由大去推导小的,再通过小的去求大的,使栈的深度太大。我们可以直接用小的去求大的,这样可以避免栈的问题。并且时间复杂度为O(n)。

//利用循环实现
public long fibonacciByFor(int n){
	int result[] = {0, 1};
	if(n < 2){
		return result[n];
	}
	long fibNMiousOne = 0;
	long fibNMiousTwo = 1;
	long fibN = 0;
	for (int i = 2; i <= n; ++i) {
		fibN = fibNMiousOne + fibNMiousTwo;
		fibNMiousOne = fibNMiousTwo;
		fibNMiousTwo = fibN;
	}
	return fibN;
}

最优解思想:

是根据推导斐波那契数列的一个矩阵数学公式


有兴趣可以去实现一下。我就只提供一种思路。它基于递归实现斐波那契的时间复杂度为O(logn)。

小结:

学会递归思想,需要深刻理解递归。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值