/** * @param {number[]} coins * @param {number} amount * @return {number} */ const coinChange = function (coins, amount) { }; /* 这个问题可以抽象成一个完全背包问题,物品的价值就是硬币的面值,物品的重量也是硬币的面值,定义dp[i][j]表示0-i类型的硬币 中,组合成j所需硬币的数量 */ function f1(coins, amount) { const m = coins.length; const n = amount; const dp = Array.from({ length: m + 1 }, () => Array(n + 1).fill(Infinity)); // 初始化:金额为0,硬币数为0 for (let i = 0; i <= m; i++) { dp[i][0] = 0; } for (let i = 1; i <= m; i++) { const coin = coins[i - 1]; for (let j = 1; j <= n; j++) { if (j < coin) { dp[i][j] = dp[i - 1][j]; // 当前硬币无法选,用上一行的结果 } else { // 可以选当前硬币(完全背包,不是 i-1) dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - coin] + 1); } } } return dp[m][n] === Infinity ? -1 : dp[m][n]; } // 上面的代码可以使用一维dp来实现,dp[i]表示找i元需要最少的硬币 function coinChange(coins, amount) { const dp = Array(amount + 1).fill(Infinity); dp[0] = 0; // 金额为 0 时需要 0 个硬币 for (let coin of coins) { for (let j = coin; j <= amount; j++) { dp[j] = Math.min(dp[j], dp[j - coin] + 1); } } return dp[amount] === Infinity ? -1 : dp[amount]; }