这篇page是针对leetcode上的70.爬楼梯所写的。小尼先简单的说明一下这道题的意思,场景模仿的是在爬楼梯的场景,我们需要爬n阶才能到达楼顶,我们每一次向上爬可以爬1或2个台阶,我们需要求出有多少种方法可以爬到楼顶。
小尼之前用动态规划的思想做过这道题,但是今天小尼想用背包问题的思想来解决,我们其实就是可以把它看作是一个完全背包问题,爬到楼顶的阶数就是对应我们背包的容量,我们可以走一阶或者两阶对应的就是我们可以放入的物品,我们可以每次向上走可以走一阶或者两阶,其实就像是我们每次可以王背包中放入大小为1或大小为2的物品,并且我们的物品可以重复去使用,所以这个问题其实就是对等一个完全背包问题。小尼接下来跟大家说明一下这里面的动规五部曲:
1、数组dp[i]所表示的含义:其实在这里表示的含义还是比较简单的,表示的就是走到第n个台阶有多少种方法。
2、递推公式:我们可以知道,这道题的思想是一个完全背包问题的模型,其实我们带入完全背包的模型就好了:if(i >= weight[i]) dp[i] = dp[i - weight[j]],所以这里的模型推导还是比较完整和简单的。
3、对dp[i]数组进行初始化:因为我们在dp[i]中记录的是方法数,其实也就是将次数一层一层的叠加,所根据完全背包的模式以及对后续结果的分析,我们可以知道我们应该定义dp[0]=1
4、确定遍历条件:这里的遍历条件就是按照完全背包的遍历方法进行遍历,我们的外层for循环遍历背包的容量,最后我们dp[i]记录的也是容量为i的背包可以放入的方法数,其实就是对应我们这道题可以到达n阶使用的方法数量。然后内层for循环遍历的是我们的物品数,其实就是我们不断地将物品放入我们的背包中,根据完全背包的条件,我们的物品可以不断地使用,其实这里也提醒我们一点就是我们在每一次调用内部的方法的时候,我们的物品其实每一次都做了是否可以放入的判断,一定那可以放入,那么我们直接就是做一个累加即可。
5、导出我们的dp[i]数组:这一步其实是我们在做完全背包的练习的时候需要做出的一步,也就是希望可以让数据显示的更加明显。但是其实在本题中不用做这一步,我们最后只需要返回一个结果就可以了。
接下来,小尼拉一下这道题的解决的代码:
class Solution {
public int climbStairs(int n) {
int[] dp = new int[n + 1];
int[] s = {1,2};
dp[0] = 1;
int len = s.length;
for(int i = 0;i <= n; i++){
for(int j = 0;j < len;j++){
if (i >= s[j]) dp[i] += dp[i - s[j]];
}
}
return dp[n];
}
}
小尼简单的对上述代码做一个解释,我们首先定义了dp数组,然后我们人为直接定义了一个物品组,其实就是用来记录我们步数对应的大小,以便我们后面可以调用对dp数组里面进行对应的添加,这里小尼再说一下这里内循环需要注意的点,就是我们在放入之前我们一定需要做一个人判断,就是容量和物品大小的判断,如果物品过大,也就这里体现我跨的步数过大,那么我们就直接跳过,只有剩下的步数大于我们将会跨的步数时,我们才可以去走(对应的就是可以往背包里放物品),最后我们只需要返回dp[n]即可。
希望上面的代码可以帮助到小伙伴们~~~