给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1
。
示例 1:
输入: coins =[1, 2, 5]
, amount =11
输出:3
解释: 11 = 5 + 5 + 1
示例 2:
输入: coins =[2]
, amount =3
输出: -1
说明:
你可以认为每种硬币的数量是无限的。
动态规划(夏令营机试题有过这一题,我当时没复习动态规划,不会做,悔恨)
动态规划最关键的一点是想好dp数组的含义。
思路是从金额0到金额amount,每一步都力求计算出所需的最少硬币数dp[i],则最终dp[amount]就是凑齐金额amount所需最少的硬币数。
class Solution {
public:
int coinChange(vector<int>& coins, int amount) {
int dp[amount+1];//dp[i]代表凑够金额i所需最少的硬币数
dp[0]=0;
for(int i=1;i<=amount;i++)
{
int min=INT_MAX;
for(int j=0;j<coins.size();j++)
{//对于每个硬币,考虑在dp[i-coins[j]]最优的情况下再取这枚硬币,会不会是取得当前金额所需硬币最少
if(i-coins[j]<0) continue; //当前金额比coins[i]小,说明不可能取过一枚coins[i]
if(dp[i-coins[j]]==INT_MAX) continue;//说明i-coins[j] 这个金额是之前没能凑不齐,因此跳过这个情况
if(dp[i-coins[j]]+1<min)
{
min=dp[i-coins[j]]+1;
}
}
dp[i]=min;
}
if(dp[amount]==INT_MAX) {//说明没能凑齐
return -1;
}
else
return dp[amount];
}
};