爬楼梯
题目链接
题目
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
输入格式
输入一个整数n,1 <= n <= 45
输出格式
输出方法个数
输入输出样例
输入:n = 3
输出:3
解释:有三种方法可以爬到楼顶。
- 1 阶 + 1 阶 + 1 阶
- 1 阶 + 2 阶
- 2 阶 + 1 阶
思路
一开始想到排列组合,因为爬楼方式就两种,一阶或二阶,相当于对不同数量的1和2进行排列组合。刚开始全采用一阶的方式,然后再增加一个二阶,减少两个一阶进行组合,直到二阶达到最大数,然后把所有排列方式加起来。
但10以后的阶乘越来越大,能超出long long的范围,所以这个方法数值偏大就不实际。
在用排列组合算出一部分答案可以得到一个规律,从n=3开始,它的方法个数等于前两个方法的和,即为一个斐波那契数列。
f(n)=f(n-1)+f(n-2)可以理解为第一次上台阶时有上一阶或两阶两种选择,选择先上一阶后剩下n-1个阶梯上去的方法加上选择先上两阶剩下n-2个阶梯上去的方法即总的方法个数。
然后就会发现,只是简单地采用递归因为不断重复计算在数据大后会造成超时,所以可以定义一个数组,记录已计算过的数值。
参考代码1
#include<stdio.h>
int a[100];
int climbStairs(int n)
{
if(n<=2) return n;
else if(a[n]!=0) return a[n];//a[n]有记录的值就直接返回减少计算
else
{
a[n]=climbStairs(n-1)+climbStairs(n-2);//没有则记录下来
return climbStairs(n-1)+climbStairs(n-2);
}
}
int main()
{
int n;
scanf("%d",&n);
printf("%d",climbStairs(n));
return 0;
}
或者可以直接写个循环,更简洁
参考代码2
#include<stdio.h>
int main()
{
int n,a[100];
a[1]=1;
a[2]=2;
scanf("%d",&n);
for(int i=3;i<=n;i++){
a[i]=a[i-1]+a[i-2];
}
printf("%d",a[n]);
return 0;
}