, ,

零钱兑换

给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount&…

给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,表示总金额。

计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1 。

你可以认为每种硬币的数量是无限的。

示例 1:

输入:coins = [1, 2, 5], amount = 11
输出:3 
解释:11 = 5 + 5 + 1

示例 2:

输入:coins = [2], amount = 3
输出:-1

示例 3:

输入:coins = [1], amount = 0
输出:0

提示:

  • 1 <= coins.length <= 12
  • 1 <= coins[i] <= 231 - 1
  • 0 <= amount <= 104

最初采用贪心算法,部分用例有问题,只是局部最优

严格来说,不能采用纯粹的贪心算法来保证解决所有的“零钱兑换”问题

为什么纯贪心行不通

贪心算法的核心是“每一步都做出当前看起来最好的选择”(即每次都拿最大面额的硬币)。这种方法只在特定的硬币面额体系下有效(比如我们现实生活中的人民币、美元体系:1, 2, 5, 10, 20, 50, 100)。

只要题目给出的硬币面额不满足这种特殊规律,贪心算法就会失效。
经典反例coins = [1, 3, 4]amount = 6

  • 贪心:先拿 4,剩下 2 只能拿两个 1。结果:4 + 1 + 1,共 3 枚。
  • 最优:拿两个 3。结果:3 + 3,共 2 枚。
var coinChange = function(coins, amount) {
    if( amount===0) return 0;
    if(coins.length <1) return 0;
    coins.sort((a,b)=>b-a)
    let num = 0;
    const res = [];
    let cur = coins.shift();
    while(cur && amount>0 ){
        if(amount >= cur){
            amount = amount - cur;
            console.log(cur,'cur')
            res.push(cur);
        }else{
            cur = coins.length ? coins.shift() : 0;
        }
    }
    console.log(res.length);
    return amount===0 ? res.length :-1;
};

采用动态规划

var coinChange = function(coins, amount) {
    const dp = new Array(amount+1).fill(Infinity);
    dp[0] = 0;
    for(let j=1; j<= amount; j++){
        for(const c of coins){
            if(j >= c){
                dp[j] = Math.min(dp[j],dp[j-c]+1); 
            }
            
        }
    }
    console.log(dp)
    return dp[amount] === Infinity ? -1 : dp[amount];
};

Previous Post

Next Post

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

About the Author

每个人都有自己得时区,在自己得时区里,一切都是准时的。

BlockSpare — News, Magazine and Blog Addons for (Gutenberg) Block Editor