题目:给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。
解:比如题目给的例子。如果想要凑成的金额是11,那么11可以由10、1<coin数组的第一个数>凑成,即凑成10最小的硬币数量加上金额为1的一个硬币;也可以由凑成2<coins数组的第二个数>的最小硬币数量加上金额为9的一个硬币。。。。求得是最小得硬币数量所以我们可以规定状态方程为dp[i] = min(dp[i], dp[i - coins[i]] + 1)。上代码,再详细细节。
class Solution {
public:
int coinChange(vector<int>& coins, int amount) {
vector<int> dp(amount + 1, -1);//题目要求不能凑成时候返回-1,所以初始化的时候选择-1
dp[0] = 0;
for (int i = 1; i <= amount; i++) {//for循环里面主要是将dp数组的数字更新为最少多少个硬币数量。
//上面说的2、9的情况,dp[9]是需要知道的,所以我们德从dp头开始更新硬币数量。
for (int j = 0; j <coins.size(); j++) {//用从前面遍历的金额遍历减coins数组的金额。
if (i - coins[j] >= 0 && dp[i - coins[j]] != -1) {//只有当减去coins数组的金额大于等于0的时候才说明可以凑成
//因为是从前遍历的,所以到11的时候之前没有更改dp[9]就不能凑成9所以也不能更改dp数组。
if (dp[i] == -1) { //初始化是-1,第一次min会选择-1,所以要使dp[i]更新正确就要保证第一次可以正确更新dp[i]。
dp[i] = dp[i - coins[j]] + 1;
}
else {
dp[i] = min(dp[i], dp[i - coins[j]] + 1);
}
}
}
}
return dp[amount];
}
};