leetcode:Coin Change

本文探讨了如何通过动态规划解决硬币兑换问题,求解构成特定金额所需的最少硬币数量,并提供了两种解决方法和相应的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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:
coins = [1, 2, 5], amount = 11
return 3 (11 = 5 + 5 + 1)

Example 2:
coins = [2], amount = 3
return -1.

Note:
You may assume that you have an infinite number of each kind of coin.

分析:题意为给你不同面值的硬币和总金额数,写一个函数去计算构成这个总金额所需的最小的硬币数目。如果硬币的任何组合都不能构成总钱数就返回-1。

思路:很明显的DP问题,一开始在想是否可以使用贪心算法,发现这样是不能保证最小coin数目的,例如:amount = 8, coins为[1, 3, 5, 6],采用贪心策略得到3(6,1,1),而实际上正确值为2(5,3),之所以贪心法在这里不适用是因为贪心所作的决策并不能确保全局最优,如果换作问题为提水,每桶都有一定量的水,怎样才能最少次数运完所有的水,这样可以用贪心选择最多的水,因为每次提越多的水,到最后的次数肯定最少。

本题两种解决办法,但是思想是一样的

1、使用线性规划法,dp[n]为amount为n的change数目,那么我们从dp[1]开始就可以DP到dp[n],迭代关系式为,dp[n] = min(dp[n], dp[n-coins[m]]+1).

2、使用递归的方法,不过有可能会造成memory exceed,递推关系为count(n,m,coins) = min(count(n,m-1,coins), count(n-coins[m],m,coins)); 其中count表示寻找最少change的函数,n为amount,m为coins(排好序的)的下标。

代码:

class Solution {
public:
    int coinChange(vector<int>& coins, int amount) {
        if(!coins.size() && amount)
           return -1;
        vector<int> dp(amount + 1,  INT_MAX);
        dp[0] = 0;
        for (auto coin : coins) {
            for (int i = coin; i <= amount; ++i) {
              if (dp[i-coin] != INT_MAX) {
                     dp[i] = min(dp[i], dp[i - coin] + 1);
                 }
             }
         }

        return dp[amount] ==  INT_MAX?-1:dp[amount];
    }
};

 参考方法2:the first recursive DFS solution

Just use the array to record the previous computed states.

class Solution {
public:
    int coinChange(vector<int>& coins, int amount) {
        if(amount<1) return 0;
        vector<int> dp(amount, 0);
        return help(coins, amount, dp);
    }

    int help(vector<int>& coins, int remain, vector<int>& dp){
        if(remain<0)   return -1;
        if(remain==0)  return 0;
        if(dp[remain-1]!=0)  return dp[remain-1];
        int min=INT_MAX;
        for(int coin : coins){
            int result=help(coins, remain-coin, dp);
            if(result>=0 && result<min)
                min=1+result;
        }
        dp[remain-1]=(min==INT_MAX ? -1 : min);
        return dp[remain-1];
    }
};

  

 

 

转载于:https://www.cnblogs.com/carsonzhu/p/5199460.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值