递归系列—1.青蛙跳台阶 (10分)
在PTA上刷题,遇到这个问题,高三的时候听数学老师讲过,当时不知道什么是递归,现在明白了,觉得有点意思。
题意:
一只青蛙一次可以跳上 1 级台阶,也可以跳上2 级。求该青蛙跳上一个n 级的台阶总共有多少种跳法。
输入格式:
首先输入数字n,代表接下来有n组输入,50>=n>=0,然后每行一个数字,代表台阶数,数字为小于60的整数
输出格式:
对每一组输入,输出青蛙的跳法。
输入样例:
3
1
2
3
输出样例:
1
2
3
我对于递归的理解是,大的问题,可以转换成相同的,但是规模减少的相同的子问题,并且子问题减少的最小还要有解(递归有基准情况)。
常见用递归解决的问题有:前n项和,阶乘(循环也可以),还有著名的汉诺塔问题。一些常见的算法也有递归的思想在里面,比如快排等等,后续会介绍。
回到这个问题,这个问题想考的是递归,但是我递归最后一个测试点超时了,后来看了看数据,阶梯数小于等于60,单个测试了n=50时就不能输出结果,爆栈了。看了网上,应该是可以优化的,在递归之前,判断一下,这个数有没有算过,算过就直接输出,中断递归。
下面介绍一下循环的算的方法,不超时。
方法一:
#include<stdio.h>
long long step(int n)
{
if (n <= 2)
return n;
long long a = 1, b = 2, c;
int i = 2;
for(i=2;i<n;i++)//后一项等于前两项之和
{
c = a + b;
a = b;
b = c;
}
return c;
}
int main()
{
int x,T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&x);
printf("%lld\n", step(x));
}
return 0;
}
讲两个坑点,这个step函数要设置成long long 型,50时候int 就超了,而且中间变量,a,b;也要设置成 long long。
方法二:
递归的方法
递归的核心就是,return。代表着子问题和原本问题的关系。在这题中,n个台阶的跳法等于n-1个台阶的跳法,加上n-2的台阶的跳法,相当于,我从n的台阶退到n-2阶的台阶,可以退一步得到n-1阶,也可以是退两步到n-2阶。
递归的结束情况,这题是,当只有一个台阶时只有一种走法,两个台阶的时候两种走法。
#include <stdio.h>
long long f[500]={0};
long long count(int n)
{
if(f[n]==0)
{
if(n==1||n==2)
return n;
else
return count(n-1)+count(n-2);
}
else
return f[n];
}
int main()
{
int T,n;
long long temp;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
if(f[n]==0)
{
temp=count(n);
f[n]=count(n);//记录算过的数
}
else
temp=f[n];
printf("%lld\n",temp);
}
return 0;
}
这是改进后的递归,加了判断,但是还是没过最后一个点,但是在调试的时候,你从40-50这十一个点是可以算出来50的,而且速度很快,说明,加的判断生效了。可以返回之前算过的数。
其实,这个题还是个斐波那契数列 (1)1 2 3 5 8 13 21…后一项是前两项之和,和兔子繁殖的题目也是一样的,感兴趣的可以去搜搜。