算法设计与分析第七次作业

leetcode 322.Coin Change

题目描述如下:

You are given coins of different denominations and a total amount of money amount. Write a function to compute the fewest number of coins that you need to make up that amount. If that amount of money cannot be made up by any combination of the coins, return -1.
Example 1:
Input: coins = [1, 2, 5], amount = 11
Output: 3
Explanation: 11 = 5 + 5 + 1
Example 2:
Input: coins = [2], amount = 3
Output: -1
Note:
You may assume that you have an infinite number of each kind of coin.

这道题要求我们找出能刚好凑出指定现金数量的硬币数量,硬币的数量给定,这道题用我们的平常思维来说肯定是尽量先选高面额的硬币,然后看下用低面额的硬币能不能刚好凑齐指定金额,如果不能,再削减高面额硬币的数量,然后继续凑,但是其实仔细一想这样的复杂度是非常高的,在最坏的情况下,根本用不到最高面额的硬币才能凑整,这样就要从最高面额的硬币从最大个数一直到0,而在最高面额硬币个数确定情况下往下凑其实又是一个子问题,复杂度是以硬币种类的阶乘往上增长的,在硬币种类一多的时候肯定不可取。

所以重点其实还是在于如何把这个问题分解成一个个的子问题,如果要找能凑齐总面额为A的硬币,不妨去找总面额为A-c_i的硬币,其中c_i为某种硬币的面额,这样在A-c_i面额数量最少时,自然也能保证在必定选一个面额为c_i的情况下,凑齐总面额为A的硬币数量也最少,而且两者只差1(即面额c_i硬币本身),所以我们可以利用动态规划的思想来解决这个问题,从总面额为0开始找,把每种总面额对应的最少硬币数都记录下来,一直找到需要的金额数量,代码如下:

class Solution {
public:
    int coinChange(vector<int>& coins, int amount) {
        int count[amount+1];
        count[0] = 0;
        for(int i = 1; i <= amount; i++){
        	count[i] = amount + 1;
        	for(int coin : coins){
        		if(i >= coin){
        			count[i] = min(count[i],count[i - coin] + 1); 
        		}
        	}
        }
        return count[amount] == amount + 1 ? -1 : count[amount];
    }
};

上面的count数组就记录了每种面额对应的最小硬币数,但是需要注意的是由于不保证某种面额一定可以被凑出来,所以我们需要对其进行识别,而在上面的代码中,我们识别的方法就是对应的count[i]==amount+1,这样做的原因是硬币面额最小为1,所以不可能出现总面额为A而需要A+1个硬币的情况,如果count[i]没有被更新过,就说明没有凑出总面额为i的方法。

上面代码的时间复杂度分析很简单,即为O(amount * n),n为硬币个数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值