目录:
一.问题表述
二.问题分析
采用列举的思考角度
转化为斐波那契数列
递归算法的利弊分析
三.启示
一.问题表述
一只青蛙要跳上一定数量的台阶,但其一次只能跳一阶或两阶,求这只青蛙跳上n上台阶有多少中跳法?
二.问题分析
因为青蛙每次只能跳一个台阶或两个台阶,因此可先对两种比较简单的情况分析:
跳一个台阶毫无疑问只有一种情况:一次跳一个;
跳两个台阶有两种情况:每次跳一个和一次跳两个;
1.采用列举的思考角度
青蛙跳上n个台阶,对青蛙所跳的每一步的所有情况都穷举出来,即可得到一共有多少种跳法。此过程可用递归来完成。以跳上六个台阶为例:(图示)
如图,青蛙每一步的每种情况都被列了出来,最后只要数出最终结果即为
2+1+2+2+1+2+1+2=13(上图中2中还有两种情况,如前文所说)
从上图可以看出每次跳跃无非使得剩余台阶数-1或-2,且易知最终都会回到剩余1个或剩余2个台阶的状况,因此我们可以以这两个情况作为递归算法的两个最终返回情况,即让f(1)=1,f(2)=2。
设这个递归算法的函数为f(x),如图2:
利用递归可让电脑完成上述自己列举,即自己一个个展开再求和的过程,并最终得到返回值。
从这个角度,我们写出代码:
小结:这个是从数学角度,对青蛙每一步所有情况进行列举并统计的方式。
2.转化为类斐波那契数列
青蛙跳一个台阶有一种跳法
青蛙跳两个台阶有两种跳法
青蛙跳三个台阶?
青蛙跳三个台阶,它第一跳无非两种情况:跳一阶和跳两阶
若跳了一阶,则还剩两阶,那么就是跳两个台阶的情况;
若跳了两阶,则还剩一阶,那么就是跳一个台阶的情况;
因此跳三个台阶时相当于先分类再相加前两种情况
即跳三个台阶=跳一个台阶+跳两个台阶。
同理,青蛙跳四个台阶:
若跳了一阶,则还剩三阶,那么就是跳三个台阶的情况;
若跳了两阶,则还剩两阶,那么就是跳两个台阶的情况;
即跳四个台阶=跳两个台阶+跳三个台阶。
再来,青蛙跳五个台阶:
若跳了一阶,则还剩四阶,那么就是跳四个台阶的情况;
若跳了两阶,则还剩三阶,那么就是跳三个台阶的情况;
即跳五个台阶=跳三个台阶+跳四个台阶。
........
既然跳n个台阶的种数可以等于跳n-1个台阶的种数加上跳n-2个台阶的种数,那么可以将这个问题转换为类似斐波那契数列来解决。即n=n-1+n-2
而对于求第n个斐波那契数列的数,我们一般有两种解决方式:递归与迭代
递归方式:
#define _CRT_SECURE_NO_WARNINGS 1 //vs2019为使用scanf函数所用。
#include <stdio.h>
int f(int n)
{
if (n == 1)
{
return 1;
}
else if (n == 2)
{
return 2;
}
else if (n > 2)
{
return f(n - 1) + f(n - 2);//递归
}
}
int main()
{
printf("青蛙要跳几个台阶=>");
int a = 0;
scanf("%d", &a);
printf("青蛙会有几种跳法=>");
printf("%d", f(a));
}
其实这个代码与上面所用从列举角度写出的代码一样,但理解方式是不同的。即一种代码的两种不同理解。
迭代方式:
斐波那契数列怎么用循环来解决呢?
我们知道斐波那契无非是前两个数相加等于第三个数,而前一个数又是它的前两个数之和。
那么我们可以这样思考:(如图所示)
图中看出a + b = c 整体不断往后一个一个数字推移,那么如何让电脑实现这个过程呢?
我们把一个个a + b = c 整体往后推的同时对整齐,上图可以发现,用一个循环,每次循环让a等于上一次的b,让b等于上一次的c,就可以让a + b = c 整体抽象地不断往后推,最后输出c的值即可。
(上图所用为常规斐波那契数列,注意我们讨论的青蛙跳台阶问题第二个数应当是2)
那么便可以写出代码:
int f(int n)
{
int a = 1;
int b = 2;
int c = 0;
while (n > 2)
{
c = a + b;
a = b;
b = c;
n--;//每次循环n减1,一直到n<=2时循环停止
}
return c;
if (n <= 2)
{
return n;
}
}
int main()
{
printf("青蛙要跳几个台阶=>");
int a = 0;
scanf("%d", &a);
printf("青蛙会有几种跳法=>");
printf("%d", f(a));
return 0;
}
3.递归算法的利弊分析
递归算法的好处:容易被想到,有一定的公式即很容易写出来;
递归算法的弊端:在此问题中,同一个情况被反复运算了多次,导致其效率低下,在输入较大数值时电脑运算时间延长。
比如下图,计算f(3)的次数
计算机重复计算了大量的f(3),再看下这个图,就明白了
这幅图中就有两个f(3)随着输入数字的增多f(3)会迅速增多,而且还有其它的数。
计算机在反复运算相同的东西,效率大大下降
与递归不同的是,循环并不是从最后一个数往回层层展开运算,而是从第一个数开始往后一个个推移,因此没有重复现象
效率大大提升
三.启示
解决问题时应当抓住问题的关键。
1.青蛙每次只能跳一个台阶或两个台阶;
2.输入的是台阶数,输出的数有多少种跳法。
3.善于用数学模型解决问题(如列举,转化为斐波那契数列等)