题目描述
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
问题分析
分析第三层楼梯,可以得出第三层可以从第一层直接爬二个两个台阶到达,也可以从第二层爬一个台阶到达,以此类推,可以用动态规划。
- 确定dp数组及下标的含义:dp[i]:爬到第i层楼梯有dp[i]种方法;
- 确定递推公式:dp[i]可以从第i-1层上一个台阶到达,也可以从第i-2层上两个台阶到达,那么递推公式:dp[i]=dp[i-1]+dp[i-2];
- 初始化dp数组:到达第一层就只有1种(1阶),即dp[1]=1;到达第二层有2种(1阶+1阶、2阶),即dp[2]=2,而dp[0]不需要用到,就不初始化了。
代码实现
// 编程软件:VS2019
// 参考书籍:代码随想录
#include<iostream>
#include<vector>
using namespace std;
// 动态规划法:时间复杂度O(n),空间复杂度O(n)
int climbStairs1(int n) {
if (n <= 1) return n;//防止出现空指针
// 注意这里要写成动态数组,不能写成 int dp[n+1];n不确定
vector<int> dp(n + 1);
dp[1] = 1;
dp[2] = 2;
// i从3开始
for (int i = 3; i <= n; i++) {
dp[i] = dp[i - 1] + dp[i - 2];
}
return dp[n];
}
// 动态规划法优化版:时间复杂度O(n),空间复杂度O(1)
int climbStairs2(int n) {
if (n <= 1) return n;
int dp[3];
dp[1] = 1;
dp[2] = 2;
for (int i = 3; i <= n; i++) {
int sum = dp[1] + dp[2];
dp[1] = dp[2]; // 不断覆盖
dp[2] = sum;
}
return dp[2];
}
int main() {
int res = climbStairs(3);
cout << res;
}
// 结果:3