跳至主要內容

Mr.He小于 1 分钟

var coinChange = function(coins, amount) {
    const memo = {}; // 借用闭包来保证 memo不被污染
    
    function dp(amt) {
        if (amt === 0) return 0;
        if (amt < 0) return -1;
        if (memo[amt] !== undefined) return memo[amt];
        
        let result = Number.MAX_SAFE_INTEGER;
        
        for (let coin of coins) {
            const sub = dp(amt - coin);
            if (sub === -1) continue;
            result = Math.min(result, sub + 1);
        }
        
        result = result === Number.MAX_SAFE_INTEGER ? -1 : result;
        memo[amt] = result;
        return result;
    }
    
    return dp(amount);
};

迭代 DP

var coinChange = function(coins, amount) {
    // 1. 创建 DP 数组,初始化为无穷大
    // 长度 amount + 1,保证下标能取到 amount
    const dp = new Array(amount + 1).fill(Infinity);
    
    // 2. 基准条件
    dp[0] = 0;
    
    // 3. 外层循环:遍历所有金额状态(从 1 开始)
    for (let i = 1; i <= amount; i++) {
        
        // 4. 内层循环:遍历所有硬币选择
        for (let coin of coins) {
            
            // 5. 约束条件:当前金额必须能容纳这枚硬币
            if (i - coin >= 0) {
                // 6. 状态转移方程
                // 这里的 dp[i] 是上一轮硬币计算后的值(或者是初始的 Infinity)
                // dp[i - coin] + 1 代表:选择了当前这枚硬币,加上剩余金额的最优解
                dp[i] = Math.min(dp[i], dp[i - coin] + 1);
            }
        }
    }
    
    // 7. 如果最终结果还是无穷大,说明无法凑出,返回 -1
    return dp[amount] === Infinity ? -1 : dp[amount];
};