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

说到求菲波那切数列中的第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[n];

    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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值