最少的硬币数目问题

题目

给定不同面额的硬币 coins 和一个总金额 amount。
编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。
你可以认为每种硬币的数量是无限的。

贪心

当给定硬币的币值非常正常的时候我们可以使用贪心算法
例如coins = [1, 2, 5,10,20], amount = 56
我们尽可能多的选择面额大的硬币即可

class Solution {
public:
    int coinChange(vector<int>& coins, int amount) {
        sort(coins.begin(),coins.end());
    	int counts=0;  //用来返回结果
        for(int i=coins.size()-1;i>=0;i--){
        	counts+=amount/coins[i];
        	amount%=coins[i];
        	if(amount==0){
        		return counts;	
        	}
        }
        return -1;	
    }
};

但是当硬币的面值比较古怪,我们就很可能得不到最优解,甚至等不到答案
比如coins = [2,3,5], amount = 9,很明显得不出答案
再比如coins = [1,2,4,5,6], amount = 9 ,用贪心得出6+2+1 ,但实际上只需要4+5

如何判断硬币的面值能否使用贪心呢?
链接一
链接二

动态规划

开一个数组,保存0~amount的最少硬币数目(比如arr[i]保存的就是amount=i时的最少硬币数目)
所以我们要求的就是arr[amount]

递推公式:
arr[amount]=min(arr[amount-coins[0]], arr[amount-coins[1] ],……, arr[amount-coins[coins.size()-1]])+1
还是很好理解的

class Solution {
public:
    int coinChange(vector<int>& coins, int amount) {
        int arr[amount+1];
        arr[0]=0;
        for(int i=1;i<amount+1;i++){
            int min1=1e9;    
            for(int j=0;j<coins.size();j++){
                if(i>=coins[j]){
                    min1=min(min1,arr[i-coins[j]]+1);
                }
            }
            arr[i]=min1;
        }
        if(arr[amount]==1e9){
            return -1;
        }
        return arr[amount];
    }
};

思考

该题每种硬币的数量是无限的,如果当每种硬币的数目都是有限个c1,c2…cn的时候,如何求解?

当硬币面额可以用贪心时,则可以用贪心来求解。
那用动态规划怎么做呢?
参考1
参考2

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

开心星人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值