给定一个代表硬币不同面值的数组,和一个硬币的总数额,求用硬币凑出该总数额的最小硬币个数。如果无法凑出该面额,返回-1。
如coins = [1, 2, 5],amount = 11。
方法一:用总额减去每一个面值,记录剩余总额,并循环进行,直到出现总额为0或者所有剩余总额都为负数。这种方法简单暴力,时间复杂度和空间复杂度都比较高。
public int coinChange(int[] coins, int amount) {
if(amount == 0)
return 0;
if(coins.length == 0)
return -1;
List<Integer> leftAmount = new ArrayList<Integer>();
leftAmount.add(amount);
for(int n = 1; n <= amount; n++){
int size = leftAmount.size();
for(int j = 0; j < size; j++){
int left = leftAmount.get(0);
leftAmount.remove(0);
for(int coin : coins){
int l = left - coin;
if(l == 0) return n;
if(l > 0) leftAmount.add(l);
}
}
if(leftAmount.size() == 0)
return -1;
}
return -1;
}
方法二:用动态规划的方法,硬币总额从0开始,一步一步地往上加,直到amount。每一步记录得到该金额的最小硬币数。
public int coinChange(int[] coins, int amount) {
if(amount<1) return 0;
int[] dp = new int[amount+1];
int sum = 0;
while(++sum<=amount) {
int min = -1;
for(int coin : coins) {
if(sum >= coin && dp[sum-coin]!=-1) { //得到sum的方法:(sum-coin)+ coin
int temp = dp[sum-coin]+1;
min = min<0 ? temp : (temp < min ? temp : min);
}
}
dp[sum] = min;
}
return dp[amount];
}