深度思考爬楼梯问题,抽取一般过程,目标是对其变式题也能认出并且求解
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
https://leetcode.cn/problems/climbing-stairs/description/
示例:

思考一:为什么可以动态规划?
动态规划是指大规模问题,可以由它的小规模问题通过动态规划方程解出,而对本题来说,到达第 i 阶台阶的方案数可以由到达第 i-1 和 第 i-2的方案数求出,动态规划方程为:
dp[i] = dp[i-1] + dp[i-2]
解释:
上述动态规划方程中,dp 表示到达第 i 阶台阶的方案数,可以由第 i-1 阶台阶走一步到达第 i 阶台阶,也可由第 i-2 阶台阶走两步到达第 i 阶台阶,所以可写出如上的动态规划方程。
思考二: 如何初始化
dp[1] = 1;
dp[2] = 2;
解释:
由状态转移方程决定了初始化的值为 dp[1] 和 dp[2] (dp[i] = dp[i-1] + dp[i-2])
从第 0 台台阶迈一步到达第 1 阶台阶,因此到达第 1 阶台阶的方案有 1 个,同理,得到 dp[2] (由第 1 阶台阶迈一步 和 由第 0 阶台阶迈两步)
class Solution {// 爬楼梯public int climbStairs(int n) {if(n == 1){return 1;} else if(n == 2){return 2;}int dp[] = new int[n+1];dp[1] = 1;dp[2] = 2;for(int i=3; idp[i] = dp[i-1] + dp[i-2];}return dp[n];}
}
给你整数 zero ,one ,low 和 high ,我们从空字符串开始构造一个字符串,每一步执行下面操作中的一种:
以上操作可以执行任意次。
如果通过以上过程得到一个 长度 在 low 和 high 之间(包含上下边界)的字符串,那么这个字符串我们称为 好 字符串。
https://leetcode.cn/problems/count-ways-to-build-good-strings/description/

让我们来看一下,本题和爬楼梯的区别和联系
dp[i] = dp[i - zero] + dp[i - one];
// 2466. 统计构造好字符串的方案数public int countGoodStrings(int low, int high, int zero, int one) {int mod = (int)(1e9 + 7);int[] dp = new int[high + 1];// 初始化int step1 = Math.min(zero, one);int step2 = Math.max(zero, one);dp[step1] = 1;dp[step2] = step2%step1==0 ? 2 : 1; // 走到 step2 的可能方案(直接走到step2、每次蹦跶step1直到蹦跶到step2)// 遍历for(int i=step1+1; i<=high; i++){if(i > step2) { // 可以由 i - step1 和 i - step2 到达dp[i] = (dp[i - step1] + dp[i - step2]) % mod;} else if(i < step2){ // 只可以由 i - step1 到达dp[i] = dp[i - step1];}}int res = 0;for(int i=low; i<=high; i++){ // 计算结果,在 low ~ high 之间的方案数res = (res + dp[i]) % mod;}return res;}
<总结> : 对一个问题,我们的求解关键是应该是抽丝剥茧,把问题捋清楚。像本文中的第二种变式题,它题目里的什么 0 1 就是误导,和 0 和 1 没关系,不要被误导,就是两种 step,给两种走不同 step 的方式!!!翻译过来就是走楼梯问题 ~~ 大家有不明白的欢迎评论区和我交流~~