《剑指offer》:[12]递归与循环-斐波那契数列

    如果我们需要重复的多次计算相同的问题,通常可以选择递归或者循环两种方法。递归是在一个函数的内部调用这个函数自身。而循环则是通过设置计算的初始值及终止条件,在一个范围内进行重复计算。
递归的优点:代码简洁;
缺点:(1)递归调用是函数自己调用自己,所以是有时间和空间的消耗的;每一次函数调用,都要在内存栈中分配空间以保存参数、返回地址和临时变量。而且往栈里压入和弹出都需要时间。
             (2)调用栈溢出问题。因为每次函数的调用都需要分配栈空间,但是每个进程的栈空间是有限的,所以递归调用的层级太多就会超出栈容量,从而导致栈溢出。
例如1+2+3+4+....+N;
             (3)递归中可能有些计算是重复的,效率你比较低下。稍后会给出实例。
利用递归和循环两种方法:
int Recursive(int number)
{
	if(number<0)
	{
		return 0;
	}
	return number=0?0:number+Recursive(number-1);
}

循环:

int Iterative(int numer)
{
	int result=0;
	for(int i=1;i<=numer;i++)
		result+=i;
	return result;
}

如果传入100,则都能算出正确的结果:


但是如果传入5000,则只有循环可以,递归就会造成栈溢出。

下面进入一个实例: 求斐波那契额数列的值。

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

还有它的变形:一直青蛙一次可以跳上以及台阶,也可以跳上2级台阶。求该青蛙跳上n级台阶总共有多少级台阶。

方案一:效率很低的解法:(导致效率很低的原因是里面有很多重复的计算,稍后会做详细的解释)
int Fibonacci(int number)
{
	if(number<=0)
		return 0;
	if(1==number)
		return 1;
	return Fibonacci(number-1)+Fibonacci(number-2);
}

此解法效率低下的原因是做了很多重复的计算,具体过程如下图:


从上图可以看出,f(2) 就被重复计算了很多次。它的时间复杂度是成指数增长的,所以效率很低,到100项的时候就能体会其中的慢了!
方案二:从下向上计算。这样实现的复杂度为O(N).主要要解决的问题是避免重复计算,其实我们也可以将计算的结果用一个数组保存起来, 这样增加了辅助空间,还有每次的查询时间复杂度为O(N).
从下向上可以避免这些问题,具体实现代码如下:
int Fibonacci(int number)
{
	int result[2]={0,1};
	if(number<=1)
		return result[number];
	int number1=1;
	int number2=0;
	int resultN=0;
	for(int i=2;i<=number;i++)
	{
		resultN=number1+number2;
		number2=number1;
		number1=resultN;
	}
	return resultN;
}













评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值