算法练习day39

79 阅读2分钟

一、爬楼梯(进阶)

之前的爬楼梯最多能爬两个台阶,如果最多能爬m个台阶,那就相当于是m个物品,每个物品可以重复取用,和上一题基本是同样的题了

五部曲

  1. dp数组,dp[i],爬到i个台阶,有多少种方法
  2. 递推公式,dp[i] += dp[i - j]
  3. dp初始化,dp[0] = 1
  4. 遍历顺序,相当于背包里求排列问题,将目标n外循环,爬台阶数m内层循环,从前往后遍历
  5. 举例推导
const readline = require('readline');
const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});
let inputArr;//存放输入的数据
rl.on('line', function(line){
  //line是输入的每一行,为字符串格式
    inputArr = line.split(' ');//将输入流保存到inputArr中(注意为字符串数组)
}).on('close', function(){
    console.log(fun(...inputArr.map(item => Number(item))))//调用函数并输出
})

function fun(n, m) {
    let dp = new Array(n + 1).fill(0)
    dp[0] = 1
    for(let i = 0; i <= n;i++) {
        for(let j = 1; j <= m;j++) {
            if(i >= j) {
                dp[i] += dp[i - j]
            }
        }
    }
    return dp[n]
}

二、零钱兑换

五部曲

  1. dp[i],凑成总金额i所需的最少个数
  2. 递推公式,dp[i] = Math.min(dp[i], dp[j-coins[j]] + 1)
  3. 初始化,dp[0] = 0,其他初始化为Infinity
  4. 遍历顺序,内层和外层遍历谁都行,都为正序遍历
  5. 举例
/**
 * @param {number[]} coins
 * @param {number} amount
 * @return {number}
 */
var coinChange = function(coins, amount) {
    let dp = new Array(amount + 1).fill(Infinity)
    dp[0] = 0
    for(let i = 0; i <= amount; i++) {
        for(let j = 0; j < coins.length; j++) {
            if(i >= coins[j]) {
                dp[i] = Math.min(dp[i], dp[i - coins[j]] + 1)
            }
        }
    }
    if (dp[amount] === Infinity) {
        return -1
    }
    return dp[amount]
};

三、完全平方数

完全平方数就是物品,凑成正整数n就是背包,解决凑成这个背包最少得物品

五部曲

  1. dp[j], 和为j的完全平方数的最少数量
  2. 递推公式,dp[j] = Math.min(dp[j], dp[j - i * i] + 1)
  3. dp初始化,dp[0] = 0,其他初始化为最大值
  4. 遍历顺序,如果求组合,外层物品,内层背包,求排列,外层背包,内层物品,该题,都可以
  5. 举例
/**
 * @param {number} n
 * @return {number}
 */
var numSquares = function(n) {
    let dp = new Array(n+1).fill(Infinity)
    dp[0] = 0
    for(let i = 1; i * i <= n;i++) {
        for(let j = i * i; j <= n;j++) {
            dp[j] = Math.min(dp[j], dp[j - i * i] + 1)
        }
    }
    return dp[n]
};