目录

70.爬楼梯

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

这道题是一个非常典型而且很简单的动态规划题目。我们可以根据动态规划题目解题的一般思路来分析:

  1. 定义状态:

dp[i]dp[i]表示爬到第ii级楼梯的不同方法数。由于每次可以选择爬 11 级或者 22 级楼梯, 所以爬到第 ii 级楼梯的方法数等于爬到第 i1i-1 级楼梯和第 i2i-2 级楼梯的方法数之和。 根据这个关系,我们可以使用动态规划的方式从 11 级楼梯开始逐步计算到第 nn 级楼梯的方法数,最终返回 dp[n]dp[n]即为结果。

  1. 设计状态转移方程:
dp[i]=dp[i1]+dp[i2]dp[i] = dp[i - 1] + dp[i - 2]
  1. 初始化:

由题目可知,dp[0]=0dp[0] = 0; dp[1]=1dp[1] = 1,这里需要特别注意的是,dp[2]dp[0]+dp[1]dp[2] \ne dp[0] + dp[1],而是dp[2]=2dp[2] = 2,所以dp[2]dp[2]也应该作为初始值

  1. 递推求解:
#include <vector>

class Solution {
public:
    int climbStairs(int n) {
        if (n <= 2) return n;
        std::vector<int> dp(n + 1);
        dp[1] = 1;
        dp[2] = 2;
        for (int i = 3; i <= n; ++i) {
            dp[i] = dp[i - 1] + dp[i - 2];
        }
        return dp[n];
    }
};
  1. 记忆优化:

从上面代码可以很容易发现,我们得出dp[i]dp[i]只需要用到dp[i1]dp[i - 1]dp[i2]dp[i -2],其他的元素其实都用不到,所以上面的代码可以优化为:

#include <vector>

class Solution {
public:
    int climbStairs(int n) {
        if (n <= 2) return n;
        int pp = 1;
        int p = 2;
        int c = 0;
        for (int i = 3; i <= n; ++i) {
            c = pp + p;
            pp = p;
            p = c;
        }
        return c;
    }
};