Coin Change

406 篇文章 0 订阅
406 篇文章 0 订阅

1,题目要求

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.

您将获得不同面额的硬币和总金额。 编写一个函数来计算构成该数量所需的最少数量的硬币。 如果这笔钱不能由任何硬币组合弥补,则返回-1。

2,题目思路

对于这道题,给定硬币的的面值种类和总的金额目标,求出最小的硬币数。

对于这个问题而言,经过分析我们可以得知,使用动态规划是一个可行的策略。
这里,我们可以定义DP[i]为总金额加和等于i的所需要的硬币的数目。
于是,我们有:

DP[i] = min(DP[i], DP[i - coins[j]] + 1);

不过,动态规划的策略运行时间较慢,这里,还有另外一种方法:将硬币按照面值从大到小的顺序进行排序,然后,利用递归的方法逐个进行尝试。

3,代码实现

1,动态规划

int x = []() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    return 0;
}();


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

2,对coin按照面值排序,递归查找

int x = []() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    return 0;
}();


class Solution {
public:
    int coinChange(vector<int>& coins, int amount) {
        //按从大到小的顺序对coin面值进行排序
        sort(coins.rbegin(), coins.rend());
        
        int ans = amount+1;
        coinHelper(coins, amount, 0, 0, ans);
        return ans == amount + 1? -1 : ans;
        
    }
private:
//idx为遍历到coins的下标,curr为当前的总coin数
    void coinHelper(vector<int>& coins, int amount, int idx, int curr, int& ans){
        if(amount == 0){
            ans = min(ans, curr);//找到了一个解,没必要再继续 (再往下只会coins数增多)
            return;
        }
        
        // coins枚举完毕,amount仍然 > 0,此组合不可行
        if (idx == coins.size()) return;
        
        // combination for coin: 0 ~ amount/coin
        const int coin = coins[idx];
        
        //coin面值从大到小,所以这样是可行的
        for(int i = amount/coin;i>=0 && curr+i<ans;i--)
            coinHelper(coins, amount-i*coin, idx+1, curr + i, ans);        
    }
};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值