题目:
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
注意:给定 n 是一个正整数。
解析:
假如要爬上第i阶(i>=2),则有两种方式:
1、从第i-1阶跳一步到第i阶
2、从第i-2阶跳两步到第i阶
记f(i)为爬上第i阶的方法数量,则
第一种方法(递归):
从公式上看,这是一个递归方程,所以首先想到的应该是采用递归的方法解决,其代码也非常简洁:
为了考虑数据的溢出,所以这里采用了long long int,到时候改回int就行了。
要正确的设定递归基 。众所周知,递归算法的一个缺陷是存在大量重复的计算,其时间复杂度为。我的机器上到n取40左右就明显速度很慢了。
#include <iostream>
#include <vector>
long long int clumbStairs(int n);
int main()
{
int n;
std::cout << "请输入阶梯数:";
while (std::cin >> n && n >= 0) {
std::cout << "共有:" << clumbStairs(n) << "种走法" << std::endl;
std::cout << "请输入阶梯数:";
}
system("pause");
return 0;
}
//这种方法时间复杂度太高
long long int clumbStairs(int n)
{
if (n == 1)
return 1;
if (n == 2)
return 2;
return clumbStairs(n - 1) + clumbStairs(n - 2);
}
第二种方法(动态规划):
由递推方程可以看出,
的结果依赖于子问题
和
的结果,所以不难写出如下的代码。
#include <iostream>
#include <vector>
long long int clumbStairs(int n);
int main()
{
int n;
std::cout << "请输入阶梯数:";
while (std::cin >> n && n >= 0) {
std::cout << "共有:" << clumbStairs(n) << "种走法" << std::endl;
std::cout << "请输入阶梯数:";
}
system("pause");
return 0;
}
long long int clumbStairs(int n) {
long long int Count = 0;
if (n > 0) {
if (1 == n)
Count = 1;
else if (2 == n)
Count = 2;
else {
long long int* dp = new long long int[n + 1];
dp[0] = 0, dp[1] = 1, dp[2] = 2;
for (int i = 3; i <= n; ++i)
dp[i] = dp[i - 1] + dp[i - 2];
Count = dp[n];
delete [] dp;
}
}
return Count;
}