解法(动态规划)
算法思路
1. 状态表⽰
dp[i] 表⽰:到达 i 位置时,⼀共有多少种⽅法。
2. 状态转移⽅程
以 i 位置状态的最近的⼀步,来分情况讨论: 如果 dp[i] 表⽰⼩孩上第 i 阶楼梯的所有⽅式,那么它应该等于所有上⼀步的⽅式之和:
i. 上⼀步上⼀级台阶, dp[i] += dp[i - 1] ;
ii. 上⼀步上两级台阶, dp[i] += dp[i - 2] ;
iii. 上⼀步上三级台阶, dp[i] += dp[i - 3] ;
综上所述, dp[i] = dp[i - 1] + dp[i - 2] + dp[i - 3] 。 需要注意的是,这道题⽬说,由于结果可能很⼤,需要对结果取模。 在计算的时候,三个值全部加起来再取模,即 (dp[i - 1] + dp[i - 2] + dp[i - 3]) % MOD 是不可取的, n 取题⽬范围内最⼤值时 。 对于这类需要取模的问题,我们每计算⼀次(两个数相加/乘等),都需要取⼀次模。如果溢出,我们的答案就错了。
3. 初始化
从我们的递推公式可以看出, dp[i] 在 i = 0, i = 1 以及 i = 2 的时候是没有办法进⾏ 推导的,因为 dp[-3] dp[-2] 或 dp[-1] 不是⼀个有效的数据。 因此我们需要在填表之前,将 1, 2, 3 位置的值初始化。 根据题意, dp[1] = 1, dp[2] = 2, dp[3] = 4 。
4. 填表顺序:
从左往右。
5. 返回值
应该返回 dp[n] 的值。
class Solution
{
public:
int waysToStep(int n)
{
// 创建表
vector<int> dp(n + 1);
// 处理边界
if (n == 1 || n == 2)
return n;
// 初始化
dp[1] = 1, dp[2] = 2, dp[3] = 4;
// 从左往右填表
for (int i = 4; i <= n; i++)
dp[i] = ((long long)(dp[i-1]) + dp[i - 2] + dp[i-3]) % 1000000007;
return dp[n];
}
};