小青蛙跳台阶
今天,要讲的是小青蛙跳台阶。
题目1:一只青蛙一次可以跳到一级台阶,也可以跳到二级台阶。求青蛙🐸跳上一个n级台阶总共有几种跳法?
递归方法
分析:如果台阶只有一级台阶的话,那么青蛙只有一种跳法;如果有两级台阶的话,有两种跳法,一种是一次跳一级,另一种是一次跳两级;如果有三级台阶的话,青蛙第一次可以跳一级,剩下的两级可以按照上面提到的跳两级台阶的跳法,若青蛙在跳三级的时候,第一次二级的话,剩下的一级只能按一级台阶的跳法来跳。以此类推,n级台阶与三级台阶的跳法思路一样。
现在我们要求跳n级台阶,有几种跳法
把n级台阶看成n的函数,记为ret(n)
台阶数 ret(n)
1 ret(1)=1
2 ret(2)=2
3 ret(3)=ret(1)+ret(2)
4 ret(4)=ret(3)+ret(2)
.... ....
n ret(n)=ret(n-1)+ret(n-2)
代码实现
#include<stdio.h>
int ret(int n)
{
if (n == 1)
return 1;
else if (n == 2)
return 2;
else
return ret(n - 2) + ret(n - 1);
}
int main()
{
int n;
printf("请输入一个台阶数:");
scanf("%d", &n);
int sum=ret(n);
printf("小青蛙共有%d种跳法\n", sum);
return 0;
}
迭代方法
如果n==100的时候,那么上面这个代码就不好计算了,因此我们可以使用迭代的算法来计算。
代码实现
#include<stdio.h>
int ret(int n)
{
int n1 = 1;
int n2 = 2;
int total = 0;
if (n == 1)
return 1;
if (n == 2)
return 2;
for (int j = 3;j <= n; j++)
{
total = n1 + n2;
n1 = n2;
n2 = total;
}
return total;
}
int main()
{
int n;
printf("请输入一个台阶数:");
scanf("%d", &n);
int sum=ret(n);
printf("#include<stdio.h>
int ret(int n)
{
if (n == 1)
return 1;
else
return 2 * ret(n - 1);
}
int main()
{
int n;
printf("请输入一个台阶数:");
scanf("%d", &n);
int sum = ret(n);
printf("小青蛙共有%d种跳法\n", sum);
return 0;
}
return 0;
}
我们把n等于100输进去,
看!!!出现负数了,这是因为结果已经超出int类型了
那如果题目变成这样子的呢?我们又该怎么解决它呢?
题目2:一只青蛙一次可以跳上一级台阶,也可以跳上二级台阶,也可以跳上三级台阶,以此类推,四级,五级......也可以跳到n级,那请问跳到n级台阶的话总共有几种跳法呢?
【注】用ret(n)表示小青蛙跳上n级台阶的跳法,给ret(0)=1
分析:
当ret(1)的时候,显然只有一种跳法,即ret(1)=1,当ret(2)的时候,第一种是一次跳到一级,还剩1个台阶,有ret(1)种跳法;第二种是,一次跳到两级,就可以跳完,还有0个台阶,有ret(0)种跳法。当n=3的时候,第一种是第一次跳到一级,剩下两个台阶有ret(2)种跳法,第二种的是,一次跳到两级 ,剩下的一个台阶有ret(1)种跳法;第三种是一次跳到三级,剩下有ret(0)种跳法。当n级台阶的时候,若第一次跳到一级,有ret(n-1)种跳法;若第一次跳到两级,有ret(n-2)种跳法.........若第一次跳到n级台阶,有ret(n-n)种跳法。
台阶数 跳法
1 ret(1)=1
2 ret(2)=ret(1)+ret(0)=2
3 ret(3)=ret(2)+ret(1)+ret(0)=4
... ...
n ret(n)=ret(n-1)+ret(n-2)+......+ret(n-n)
分析: ret(n)=ret(n-1)+ret(n-2)+......+ret(n-n)大家可以把它认为是:ret(n)=ret(0)+ret(1)+........ret(n-1)
那么ret(n-1)=ret(0)+ret(1)+ret(2)+.......+ret(n-2)
把ret(n-1)代入到ret(n)中,发现了ret(n)=2*ret(n-1) (n>1)是由ret(n)-ret(n-1)=ret(n-1)推出来的
这样子,经过推理,我们可以很清楚的怎么写这个问题的代码了
代码实现
#include<stdio.h>
int ret(int n)
{
if (n == 1)
return 1;
else
return 2 * ret(n - 1);
}
int main()
{
int n;
printf("请输入一个台阶数:");
scanf("%d", &n);
int sum = ret(n);
printf("小青蛙共有%d种跳法\n", sum);
return 0;
}
总结
从上面的例子上,我们可以很清楚的了解到递归其实就是重复调用函数自身实现循环。优点就是a.用有限的循环语句实现无限集合;b.代码易于理解;c.大问题转化成小问题。缺点:a.递归不断调用函数,导致浪费空间;b.容易导致堆栈溢出。迭代函数内某段代码实现循环。优点就是a.效率高,代码运行的时间只会随循环的增加而增加,相对于递归的话,它没有额外开销。缺点:a.代码难推理;b.相对于代码它没递归的好理解。写者可以根据利弊来写代码。