给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。
示例 1:
输入: coins = [1, 2, 5], amount = 11
输出: 3
解释: 11 = 5 + 5 + 1
示例 2:
输入: coins = [2], amount = 3
输出: -1
说明:
你可以认为每种硬币的数量是无限的。
============================================================================
动态规划
状态转移方程:dp[ i ] = min( i -coins[0] , i -coins[1] , … , i -coins[j] )+1
下面的是leetCode官方的代码
public int coinChange(int[] coins, int amount) {
int len = coins.length;
int max = amount+1;
int[] dp = new int[amount + 1];
Arrays.fill(dp,max);
dp[0]=0;
for (int i=1;i<=amount;i++){
for (int j=0;j<len;j++){
if (coins[j]<=i){
dp[i]=Math.min(dp[i],dp[i-coins[j]]+1);
}
}
}
return dp[amount]>amount?-1:dp[amount];
}
dfs
private int ans ;
private int[] coins;
public int coinChange(int[] coins, int amount){
int len = coins.length;
if (amount<0){
return -1;
}
if (amount==0){
return 0;
}
if (len<0){
return -1;
}
Arrays.sort(coins);
ans = Integer.MAX_VALUE;
this.coins=coins;
dfs(len-1,amount,0);
return ans==Integer.MAX_VALUE?-1:ans;
}
private void dfs(int c_index, int amount, int count) {
if (c_index<0){
return;
}
int c = coins[c_index];
for (int k = amount/c;k>=0;k--){
int remain = amount - k*c;
int newCount = count+k;
if (remain==0){
ans = Math.min(newCount,ans);
return;
}
if (newCount+1>=ans){
return;
}
dfs(c_index-1,remain,newCount);
}
}