C语言每日一题:青蛙跳楼梯(学习笔记自用)

今天做了一道csdn上的题,即一个青蛙一次能跳1或2个梯子,请问他跳n阶梯子有多少种跳法?我当时一开始用的是数学排列组合里的分类计算法,先计算全部一个一个跳、又一次跳了两个、两次跳了两个。。。后来在看解析,觉得不愧是大佬,居然结合了斐波那契数列!

原作者的方法是这样的:如果n=1,则只有1种跳法。如果n=2,有两种。n>2,我们可以发现可以按照第一次跳一节还是两节来分类,如果f(n)表示n阶梯子有多少种跳法,那么f(n)=第一次跳一节的跳法+第一次跳两节的跳法。第一次跳一节,还剩n-1节,有f(n-1)种跳法;第一次跳2

节就有f(n-2)种跳法。因此n>2之后就可以表示为f(n)=f(n-1)+f(n-2)。这样就形成了一个与斐波那契数列原理相同的代码。

但是,区别大佬和菜鸟的重要指标不是看能不能完成任务,而是代码的效率。大佬能发现上面的方法会有重复计算的情况,因为我们需要用到递归,那么f(n-1)和f(n-2)就会有递归过程中重复计算。如何避免呢?

可能确实因为自己太菜或者根本没停下来想,


解决递归函数中重复计算的方法:数组储存法

以前没有意识到数组的一个基本用途:储存(说明纸上得来终觉浅,绝知此事要躬行!)

我们大可以现算出f(0)到f(n)的值储存在一个数组中,然后随用随拿。

long int f[1000]={0};  //定义一个较大数组

int jump(int n){
    //当只有一阶台阶的时候,只有一种上台阶的方式。
    
    //当有2阶台阶的时候,有2种上台阶的方式,一种是一次上一阶,还有一种是一次上2个台阶。
    
    //现在设有n阶台阶,如果n>2,那种应该有(先跳一阶)+(先跳2阶)的方式
    
    //如果先跳一阶,那么就有jump(n-1)中方式。如果先跳2阶,那么就有jump(n-2)中方式。
    
    //因此可以知道共有jump(n-1) + jump(n-2)种方式。
    if(n==1)
    {
        f[1]=1;
        return f[1];
    }

    if(n==0)
    {
        f[0]=1;
        return f[0];
    }

    if(n==2)
    {
        f[2]=2;
        return f[2];
    }                                             //先储存f(0)、(1)、(2)
    else
    {
        if(f[n-1]!=0)
        {
            if(f[n-2]!=0)                      //说明前两个数已经算出
            {
                return (f[n-1]+f[n-2]);
            }
            else
            {                                             
                f[n-2]=jump(n-2);
                return (f[n-1]+f[n-2]);
            }
        }
        else
        {
            if(f[n-2]!=0)
            {
                f[n-1]=jump(n-1);
                return (f[n-1]+f[n-2]);
            }
            else
            {
                f[n-1]=jump(n-1);
                f[n-2]=jump(n-2);
                return (f[n-1]+f[n-2]);             //谁不知道谁就进入递归知道算出来并补上空为止
            }
        }
    }
}
原文为CSDN博主「飞向星的客机」的原创文章
原文链接:https://blog.csdn.net/m0_63325890/article/details/122499099


但很快我们又可以发现:预留的空间太占内存,可以利用刚学过的动态内存!

但显然,大佬发现了更简便的方法:我们用逆序思维,n阶楼梯我们需要算出n-1阶+n-2阶楼梯的方法,n-1阶需要知道n-2阶和n-3阶方法。。。。那么一直这样下去,会算到3阶楼梯需要知道f(1)+f(2)=3.那么我们到这来:1+2=f(3);f(2)+f(3)=f(4)....f(n)=f(n-1)+f(n-2)

这样,我们就可以另第一个加数为a,第二个为b,下面上一段伪代码

a=1;b=2;

sum=a+b

a=b;b=sum;

这样循环n-2次即可得到f(n)


总结一下这个基础题的火花:

1,避免重复计算的方法——储存,储存的方法——数组

2,计算有规律的问题,建议先用笔写出来,找到规律。至于找规律的方法,今天学到一个逆向思维法。寻找该项与前一项、前两项的关系。

3,计算方法数,可以以第一次选择来分类。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值