您的位置:首页 > 编程语言 > C语言/C++

菲波那切数列的递归与非递归解法以及青蛙跳台阶问题

2017-11-08 16:01 246 查看
说到求菲波那切数列中的第n个数,大家首先想到的就是递归解法,简单易懂。

long long Fibonacci(int n)
{
if (n <= 0)
return 0;
if (n == 1)
return 1;
return Fibonacci(n - 1) + Fibonacci(n - 2);
}


但每一次的递归都会是一次函数的调用,会为参数和变量分配空间,所以递归的次数越多,就容易导致栈溢出。而且,当递归深度较深时,递归的效率会很低。所以,递归求解并不是一个高效的解法。这个时候用循环求解效率会高于递归。

long long Fib(unsigned int n)
{
int ret[2] = { 0, 1 };
if (n < 2)
return ret
;

long long fibOne = 1;
long long fibTwo = 0;
long long FibN = 0;
for (unsigned int i = 2; i <= n; ++i)
{
FibN = fibOne + fibTwo;
fibTwo = fibOne;
fibOne = FibN;
}
return FibN;
}


我们来对比一下两者的效率:

int main()
{
int start1 = GetTickCount();
Fibonacci(40);
int end1 = GetTickCount();
cout << end1 - start1 << endl;
int start2 = GetTickCount();
Fib(40);
int end2 = GetTickCount();
cout << end2 - start2 << endl;
system("pause");
return 0;
}




题目一:一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。

当n = 1, 只有1种中跳法;当n = 2时,有两种跳法;当n = 3 时,有3种跳法;当n = 4时,有5种跳法;当n = 5时,有8种跳法;…….

经过分析,我们可以发现,这道题其实就是一个斐波那契数列问题,解法同上。

题目二:变态跳台阶。

一个台阶总共有n级,如果一次可以跳1级,也可以跳2级……它也可以跳上n级。此时该青蛙跳上一个n级的台阶总共有多少种跳法?

(1)分析:用Fib(n)表示青蛙跳上n阶台阶的跳法数,青蛙一次性跳上n阶台阶的跳法数1(n阶跳),设定Fib(0) = 1;

当n = 1 时, 只有一种跳法,即1阶跳:Fib(1) = 1;

当n = 2 时, 有两种跳的方式,一阶跳和二阶跳:Fib(2) = Fib(1) + Fib(0) = 2;

当n = 3 时,有三种跳的方式,第一次跳出一阶后,后面还有Fib(3-1)中跳法; 第一次跳出二阶后,后面还有Fib(3-2)中跳法;第一次跳出三阶后,后面还有Fib(3-3)中跳法

Fib(3) = Fib(2) + Fib(1)+Fib(0)=4;……..



//递归
long long Fib(int n)
{
if (n == 0)
return 0;
if (n == 1)
return 1;
if (n == 2)
return 2;
else
return (2 * Fib(n - 1));
}


题目三:矩形覆盖问题。

用2*1的小矩形,横着或竖着去覆盖更大的矩形,请问用8个2*1的小矩形无重叠地覆盖一个2*8的大矩形,总共有多少种方法?



我们把2*8的覆盖方法记为f(8).用第一个1*2的小矩形去覆盖大矩形的最左边时有两个选择,竖着放或者横着放。当竖着放的时候,右边还剩下2*7的区域,这种情况的覆盖方法我们记为f(7).当把第一个小矩形横着放的时候,左下角必须放一个1*2的小矩形,而右边还有2*6的区域,这种情况下的覆盖方法称为f(6).所以,f(8)=f(7)+f(6).

通过上面的分析,我们可以看出,这道题其实也是斐波那契数列的应用。

nt fibonacci(int n)
{
int num1 = 1, num2 = 1, num3 = 0, i = 0;
if (n <= 1)
{
return num1;
}
for (i = 1; i < n; i++)
{
num3 = num1 + num2;
num1 = num2;
num2 = num3;
}
return num3;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c++