【温故知新】`70. 爬楼梯进阶版` 完全背包🎒问题AC-动态规划实现

1,225 阅读3分钟

题目描述

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

注意:给定 n 是一个正整数。

示例 1:

输入: 2 输出: 2 解释: 有两种方法可以爬到楼顶。

  1. 1 阶 + 1 阶
  2. 2 阶 示例 2:

输入: 3 输出: 3 解释: 有三种方法可以爬到楼顶。

  1. 1 阶 + 1 阶 + 1 阶
  2. 1 阶 + 2 阶
  3. 2 阶 + 1 阶

来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/cl… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路

题目分析爬1个台阶还是2个台阶,重复多次使用,完成n阶楼梯的问题:

  • 完全背包问题的动态规划;
  • 确定dp含义:dp[j]表示j阶台阶有n种方式达到楼顶;
  • 确定dp递推公式:
    • 爬第n阶楼梯的方法数量,等于 2 部分之和
    • 爬上 n-1 阶楼梯的方法数量。因为再爬1阶就能到第n阶
    • 爬上 n-2 阶楼梯的方法数量,因为再爬2阶就能到第n阶
    • 因此递推公式:dp[j]=dp[j-1]+dp[j-2]
  • dp数组初始化:
    • dp[0]=0;dp[1]=1;dp[2]=2;实际含义n>0,仅作为递推基础;其他非0下标初始化为0;
  • 遍历顺序:遍历容量n;再遍历物品;

代码

/**
 * @param {number} n
 * @return {number}
 */
var climbStairs = function(n) {

    if(n<=2){
        return n;
    }
    let dp=new Array(n+1).fill(0);
    dp[0]=0;dp[1]=1;dp[2]=2
    //物品 1、2可以重复多次使用,填满容量为n的容器;
    //此时容量为steps=[1,2];
    for(let j=3;j<=n;j++){
      dp[j]=dp[j-1]+dp[j-2]

    }
    return dp[n]
   
};

爬楼梯进阶版

题目描述

每次可以爬m个台阶呢? 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

每次你可以爬的台阶数为steps[i];0<i<m; steps[1,2,3,4,5,...m]。 你有多少种不同的方法可以爬到楼顶呢?

注意:给定 n 是一个正整数。m<n; image.png

解题思路

  • 完全背包问题的动态规划;

  • 确定dp含义:dp[j]表示j阶台阶有n种方式达到楼顶;

  • 确定dp递推公式:

    • 爬第n阶楼梯的方法数量
    • dp[j]=dp[j]+dp[j-steps[i]]
  • dp数组初始化:

    • dp[0]=1;实际含义n>0,仅作为递推基础;其他非0下标初始化为0;
  • 遍历顺序: 此时问题转化为完全背包🎒问题排列解的问题:

    可参考完全背包🎒问题377

总结

在求装满背包🎒问题顺序关键在于:

如果求组合数就是外层for循环遍历物品,内层for遍历背包。 如果求排列数就是外层for遍历背包,内层for循环遍历物品。

代码

/**
 * @param {number} n
 * @return {number}
 */
var climbStairs = function(steps,n) {

    let dp=new Array(n+1).fill(0);
    dp[0]=1
    //可以steps[i]重复多次使用,填满容量为n的容器;
    for(let j=1;j<=n;j++){
        for(let i=0;i<steps.length;i++>){
            if(j-steps[i]>=0){
                 dp[j]+=dp[j-steps[i]]   
            }
        }

    }
    return dp[n]
   
};

以下代码完全AC:

所以本题目完全可以使用完全背包🎒问题去解决:

/**
 * @param {number} n
 * @return {number}
 */
var climbStairs = function(n) {
   
    
    let dp=new Array(n+1).fill(0);
    dp[0]=1
    const steps=[1,2]// 假设steps 有以下几种方式1、2;
    //物品 1、2可以重复多次使用,填满容量为n的容器;
    for(let j=1;j<=n;j++){  //遍历容量
        for(let i=0;i<steps.length;i++){ // 遍历物品;
            if(j-steps[i]>=0){ // 当前容量大于当前物品
               dp[j]+=dp[j-steps[i]] 
            }
        }
    }
    return dp[n]
   
};

完全背包🎒问题

【温故知新】322. 零钱兑换 动画演示-完全背包问题最小解-动态规划实现

【温故知新】518. 零钱兑换 II 完全背包问题组合解-动态规划实现

【温故知新】377. 组合总和 Ⅳ 完全背包问题排列解-动态规划实现

01背包🎒问题

【温故知新】474. 一和零 01背包🎒问题最大解-动态规划实现

【温故知新】494. 目标和 表达式转化为01背包🎒问题-动态规划实现

【温故知新】1049. 最后一块石头的重量 II 最小重量转化为01背包🎒问题最大解-动态规划实现

【温故知新】416. 分割等和子集01背包🎒问题存在解-动态规划实现