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.

Example1:

coins = [1, 2, 5], amount = 11
return 3 (11 = 5 + 5 + 1)

Example2:

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

Note:

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

分析:

题目的要求是给定一些不同面值的硬币,问是否可以通过这些硬币配凑出给定的面值。
可以很容易地分析出,题目与完全背包问题是同一类型的问题。
让我们回忆一下什么是完全背包问题:

有N种物品和一个容量为V的背包,每种物品都有无限件可用。放入第i种
物品的费用是Ci,价值是Wi。求解:将哪些物品装入背包,可使这些物品的耗 费的费用总和不超过背包容量,且价值总和最大。

可以看到,完全背包问题与本题十分相似,只是做了些许的改变而已。
将本题中的每个硬币的面值等同于完全背包问题中没见物品的体积,而将要求的面值等同于背包的容量。最后,我们发现,背包问题中每件物品的费用Ci其实也是对应于每种硬币的面值,只是,这个条件在这个问题中并不重要,因为,题目的要求是获得某一面值所需要的最少的硬币数,因此,需要的硬币数也就作为我们度量结果的一个标准了。
我们可以看到,完全背包问题的解法的伪代码如下:

F[0..V]←0 
for i ← 1 to N 
for v ← Ci to V 
F[v] ← max(F[v], F[v −Ci] +Wi)

可以看到,在第i次迭代中,F[v]表示的是对于容量为v的背包,前i件物品装进背包能获得的最大的价值,其中的状态转移方程也是01背包问题的状态转移方程。
现在,回过头来考虑本题,首先,应该也有一个状态转移方程以及方程变量的初始值。
用dp[i, v]来表示只使用前i种硬币获得总面值为v所需要的最少的硬币数。
可以写出状态转移方程如下:

dp[i, v] = min(dp[i - 1, v - K*coins[i]] + K)

同样,可以与完全背包问题的解法的空间复杂度的优化思想一样,用dp[v]来表示在第i次迭代(即用前i种硬币)获得总面值为v所需要的最少的硬币数。
接下来,就需要考虑d[v]的初始化的问题,有d[v]的物理意义可以知道,dp[v]的初始化的值表示的是不适用硬币达到v的面值,可以发现,只有v = 0的时候才可以实现,且dp[0]的值是0,而对于其他的面值,是无法达到的,此时,在本题中,可以将dp[v | v > 0]的值置为amount + 1,因为,在本题中硬币最小的面值是1,所以,达到amount面值最多也就需要amount个硬币,置为amount + 1表示不可达到。

代码:

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

运行结果

这里写图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值