C语言每日一练——第90天:青蛙跳台阶(升级版)_一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶(2)

img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

n

n

n 的数组,用于在递归时存储

f

(

0

)

f(0)

f(0) 至

f

(

n

)

f(n)

f(n) 的数字值,重复遇到某数字时则直接从数组取用,避免了重复的递归计算。
 
所以我们设置一个数组,用于存放第一次计算某一个

n

n

n的jump(n)
 
当每一次要计算一个jump(n)的时候,就先查看数组中以

n

n

n 为下标的地方是否有值,有的话就可以不调用jump(n),而直接从数组中取得结果值,否则再计算jump(n)

📝代码实现

#include <stdio.h>

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];
    }
    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]);
            }
        }
    }
}

int main()
{
    int num = 0;
    printf("请输入一个台阶数:> ");
    scanf("%d", &num);

    int ret = jump(num);

    printf("小青蛙有 %d种 跳法\n", ret);
    return 0;
}

运行结果👇

在这里插入图片描述

🍅 动态规划解法

很快我又发现,不必把所有的记录都记起来;
 
假设我有3阶楼梯,我只需要知道跳2阶跳1阶的方法数是多少就可以算出跳3阶的方法数;
 
因此每次只需要保留 **n

1

n-1

n−1阶** 和 **n

2

n-2

n−2阶** 的方法数。

📝代码实现

#include <stdio.h>

int jump(int n)
{
    //n=0、1、2的时候,直接返回n即可
    if (n < 3)
    {
        return n;
    }
    
    //第一个数为1
    int one = 1;

    //第二个数为2
    int two = 2;

    //用于存放前两个数之和
    int sum = 0; 
    while (n > 2)
    {
        sum = one + two;
        one = two;
        two = sum;

        n--;
    }
    return sum;
}

int main()
{
    int num = 0;
    printf("请输入一个台阶数:> ");
    scanf("%d", &num);

    int ret = jump(num);

    printf("小青蛙有 %d种 跳法\n", ret);
    return 0;
}

运行结果👇

在这里插入图片描述

2. 问题升级

🍑 题目描述

一只青蛙一次可以跳上一级台阶,也可以跳上二级台阶……,也可以跳n级,求该青蛙跳上一个n级的台阶总共需要多少种跳法。

🍑 解题思路

一只青蛙要想跳到n级台阶,可以从一级,二级……,也就是说可以从任何一级跳到n级👇
在这里插入图片描述
当台阶为1级时,

f

(

1

)

=

1

f(1)=1

f(1)=1;
 
当台阶为2级时,

f

(

2

)

=

1

1

=

2

f(2)=1+1=2

f(2)=1+1=2;
 
当台阶为3级时,

f

(

3

)

=

f

(

1

)

f

(

2

)

1

=

4

f(3)=f(1)+f(2)+1=4

f(3)=f(1)+f(2)+1=4;
 
当台阶为4级时,

f

(

4

)

=

f

(

1

)

f

(

2

)

f

(

3

)

1

=

8

f(4)=f(1)+f(2)+f(3)+1=8

f(4)=f(1)+f(2)+f(3)+1=8;
 
当台阶为5级时,

f

(

5

)

=

f

(

1

)

f

(

2

)

f

(

3

)

f

(

4

)

1

=

16

f(5)=f(1)+f(2)+f(3)+f(4)+1=16

f(5)=f(1)+f(2)+f(3)+f(4)+1=16;
 
所以递推公式我们很容易就能想到:

f

(

n

)

=

f

(

n

1

)

f

(

n

2

)

f

(

2

)

f

(

1

)

f

(

0

)

f(n)=f(n-1)+f(n-2)+……+f(2)+f(1)+f(0)

f(n)=f(n−1)+f(n−2)+……+f(2)+f(1)+f(0)
 
最后这个

f

(

0

)

f(0)

f(0)是可以去掉的,因为0级就相当于没跳,所以

f

(

0

)

=

0

f(0)=0

f(0)=0
 
然后我们把

f

(

0

)

f(0)

f(0)去掉再转换一下:

f

(

n

1

)

=

f

(

n

2

)

f

(

n

3

)

f

(

2

)

f

(

1

)

f(n-1)=f(n-2)+f(n-3)+……+f(2)+f(1)

f(n−1)=f(n−2)+f(n−3)+……+f(2)+f(1);

推导过程👇

我们列两个等式:
 

f

(

n

)

=

f

(

n

1

)

f

(

n

2

)

f

(

n

3

)

f

(

2

)

f

(

1

)

f(n) = f(n-1) + f(n-2) +f(n-3) + … + f(2) + f(1)

f(n)=f(n−1)+f(n−2)+f(n−3)+…+f(2)+f(1)
 

f

(

n

1

)

=

f

(

n

2

)

f

(

n

3

)

f

(

2

)

f

(

1

)

f(n-1) = f(n-2) +f(n-3) + … + f(2) + f(1)

f(n−1)=f(n−2)+f(n−3)+…+f(2)+f(1)
 
由①-②得,

f

(

n

)

=

2

f

(

n

1

)

f(n) = 2f(n-1)

f(n)=2f(n−1)

🍑 代码实现

🍅 递归方法

📝代码示例

int jump(int n)
{
    if (n == 1)
    {
        return 1;
    }
    else
    {
        return 2 \* jump(n - 1);
    }
}

int main()
{
    int num = 0;
    printf("请输入一个台阶数:> ");
    scanf("%d", &num);

    int ret = jump(num);

    printf("小青蛙有 %d种 跳法\n", ret);
    return 0;
}

运行结果👇

在这里插入图片描述

🍅 非递归方法

当然这里也可以用非递归的方式来实现
 
那么非递归怎么去思考呢?
 
可以这样理解:

f

(

1

)

=

1

=

2

0

f(1) = 1 = 2^0

f(1)=1=20

f

(

2

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

int jump(int n)
{
    if (n == 1)
    {
        return 1;
    }
    else
    {
        return 2 \* jump(n - 1);
    }
}

int main()
{
    int num = 0;
    printf("请输入一个台阶数:> ");
    scanf("%d", &num);

    int ret = jump(num);

    printf("小青蛙有 %d种 跳法\n", ret);
    return 0;
}

运行结果👇

在这里插入图片描述

🍅 非递归方法

当然这里也可以用非递归的方式来实现
 
那么非递归怎么去思考呢?
 
可以这样理解:

f

(

1

)

=

1

=

2

0

f(1) = 1 = 2^0

f(1)=1=20

f

(

2

[外链图片转存中…(img-BhtASvms-1715741765506)]
[外链图片转存中…(img-Sb8q3jex-1715741765507)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值