题目描述:
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
注意:给定 n 是一个正整数。
示例 1:
输入: 2
输出: 2
解释: 有两种方法可以爬到楼顶。
1. 1 阶 + 1 阶
2. 2 阶
示例 2:
输入: 3
输出: 3
解释: 有三种方法可以爬到楼顶。
1. 1 阶 + 1 阶 + 1 阶
2. 1 阶 + 2 阶
3. 2 阶 + 1 阶
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/climbing-stairs
思路:
定义子问题
problem(i) = problem(i-1) + problem(i-2) //即求到第 i 层楼梯的方法数等于求解第 i-1 和 第 i-2 层楼梯方法数的和。
状态转移方程
dp[i] = dp[i-1] + dp[i-2]
复杂度优化
由于我们每次只关注当前层数的前两个状态,所以可以用两个变量保存 i-1 和 i-2。(将一维数组降维成点)
class Solution {
public:
int climbStairs(int n) {
int pre = 1;
int cur = 1;
for(int i=2; i<=n; ++i)
{
int tmp = pre + cur;
pre = cur;
cur = tmp;
}
return cur;
}
};
考虑将问题一般化:
我们现在是给出了可能的走法,走1层或者走2层。如果更加泛化呢,如可能的走法用数组给出,arr[2,3,5]。又该如何处理呢?
我们只需要修改我们的dp 方程就好。如:dp[i] = dp[i-2] + dp[i-3] + dp[i-5],即 dp[i] += dp[i-j] (j=2,3,5)
class Solution {
public:
int climbStairs(int n) {
vector<int> dp(n,0);
dp[0] = 1;
for(int i=2; i<=n; ++i)
{
for(int j=0; j < steps.size(); ++j)
{
int step = steps[j];
if( i< step) continue; //台阶小于要跨越的步数
dp[i] += dp[i-step];
}
}
return dp[n];
}
};

本文探讨了经典的爬楼梯问题,通过动态规划方法解决。详细解析了如何使用递推公式计算达到楼顶的不同方法数量,同时提供了一般化的解决方案,适用于多种可能的步数选择。
473

被折叠的 条评论
为什么被折叠?



