爬楼梯
力扣:70. 爬楼梯 - 力扣(LeetCode)
之前讲这道题⽬的时候,因为还没有讲背包问题,所以就只是讨论了⼀下爬楼梯最直接的动规⽅法(斐波那契)。
这次终于讲到了背包问题,我们一起再来爬⼀次楼梯!
假设你正在爬楼梯。需要 n
阶你才能到达楼顶。每次你可以爬 1
或 2
个台阶。你有多少种不同的方法可以爬到楼顶呢?
示例 1:
输入: n = 2
输出: 2
解释: 有两种方法可以爬到楼顶。
- 1 阶 + 1 阶
- 2 阶
示例 2:
输入:n = 3
输出:3
解释:有三种方法可以爬到楼顶。
- 1 阶 + 1 阶 + 1 阶
- 1 阶 + 2 阶
- 2 阶 + 1 阶
这题我们在动态规划基础部分03爬楼梯 - 掘金 (juejin.cn)中已经讲过⼀次了,原题其实是⼀道简单动规的题⽬。既然这么简单为什么还要讲呢,其实本题稍加改动就是⼀道⾯试好题。
改为:⼀步⼀个台阶,两个台阶,三个台阶,.......,直到 m个台阶。问有多少种不同的⽅法可以爬到楼
顶呢?
1阶,2阶,.... m阶就是物品,楼顶就是背包。
每⼀阶可以重复使⽤,例如跳了1阶,还可以继续跳1阶。问跳到楼顶有⼏种⽅法其实就是问装满背包有⼏种⽅法。 此时⼤家应该现这就是⼀个完全背包问题了!
和上一篇文章的动态规划完全背包问题03:组合总和 Ⅳ - 掘金 (juejin.cn)基本上就是一道题了。
动规五部曲:
1. 确定dp数组以及下标的含义
dp[i]:爬到有i个台阶的楼顶,有dp[i]种⽅法。
2. 确定递推公式
在前面的文章我们都讲过了,求装满背包有⼏种⽅法,递推公式⼀般都是dp[i] += dp[i - nums[j]];
本题呢,dp[i]有⼏种来源,dp[i - 1],dp[i - 2],dp[i - 3]....dp[i - j]等等,即:dp[i - j]。
那么递推公式为:dp[i] += dp[i - j]。
3. dp数组如何初始化
⾸先dp[0]⼀定要为1,dp[0] = 1是 递归公式的基础。 从dp[i]的含义上来讲就是,凑成总⾦额0的货币组合数为1。 下标⾮0的dp[j]初始化为0,这样累计加dp[j - coins[i]]的时候才不会影响真正的dp[j]。
4. 确定遍历顺序
这是背包⾥求排列问题,即:1、2 步 和 2、1 步都是上三个台阶,但是这两种⽅法不⼀样!所以需将target放在外循环,将nums放在内循环。每⼀步可以⾛多次,这是完全背包,内循环需要从前向后遍历。
遍历顺序和举例推导dp数组和动态规划基础部分03爬楼梯 - 掘金 (juejin.cn)一样我就不继续下去了直接上代码!
Java代码如下:
class Solution {
public int climbStairs(int n) {
int[] L = new int[n + 1];
L[0] = 1;
for(int i = 1; i < L.length; i++)
for(int j = 1; j <= 2; j++)
if(i >= j)
L[i] += L[i - j];
return L[n];
}
}
代码中m表示最多可以爬m个台阶,代码中把m改成2就是本题70.爬楼梯可以AC的代码了。