如果我们需要重复的多次计算相同的问题,通常可以选择递归或者循环两种方法。递归是在一个函数的内部调用这个函数自身。而循环则是通过设置计算的初始值及终止条件,在一个范围内进行重复计算。
递归的优点:代码简洁;
缺点:(1)递归调用是函数自己调用自己,所以是有时间和空间的消耗的;每一次函数调用,都要在内存栈中分配空间以保存参数、返回地址和临时变量。而且往栈里压入和弹出都需要时间。
(2)调用栈溢出问题。因为每次函数的调用都需要分配栈空间,但是每个进程的栈空间是有限的,所以递归调用的层级太多就会超出栈容量,从而导致栈溢出。
例如1+2+3+4+....+N;
(3)递归中可能有些计算是重复的,效率你比较低下。稍后会给出实例。
利用递归和循环两种方法:
方案二:从下向上计算。这样实现的复杂度为O(N).主要要解决的问题是避免重复计算,其实我们也可以将计算的结果用一个数组保存起来, 这样增加了辅助空间,还有每次的查询时间复杂度为O(N).
从下向上可以避免这些问题,具体实现代码如下:
递归的优点:代码简洁;
缺点:(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);
}
此解法效率低下的原因是做了很多重复的计算,具体过程如下图:
方案二:从下向上计算。这样实现的复杂度为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;
}