给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。
你可以认为每种硬币的数量是无限的
解答:
方法1、动态规划
count[amount] = min{ count[amount - coins[0]], count[amount - coins[1]], ..., count[amount - coins[n - 1]] } + 1
public int coinChange(int[] coins, int amount) { if (amount == 0) { return 0; } int[] count = new int[amount + 1]; Arrays.fill(count, amount + 1); count[0] = 0; for (int i = 1; i < amount + 1; ++i) { for (int j = 0; j < coins.length; ++j) { if (i >= coins[j]) { count[i] = Math.min(count[i], count[i - coins[j]] + 1); } } } return count[amount] > amount ? -1 : count[amount]; }
方法2、dfs
private int res = Integer.MAX_VALUE; public int coinChange(int[] coins, int amount) { if (amount == 0) { return 0; } Arrays.sort(coins); dfs(coins, amount, 0, coins.length - 1); return res == Integer.MAX_VALUE ? -1 : res; } private void dfs(int[] coins, int amount, int count, int index) { // index小于零,或者,全部选择当前的结果大于等于res,不取 if (index < 0 || count + amount / coins[index] >= res) { return; } // 否则,index大于零,并且,全部选择当前的结果小于res,考虑取 if (amount % coins[index] == 0) { // 整除,直接取(由于已排序,已经最小,可以直接返回) res = count + amount / coins[index]; return; } // 不整除,数量从[amount / coins[index]~0], 取当前。递归取下一个index-1 for (int i = amount / coins[index]; i >= 0; --i) { dfs(coins, amount - i * coins[index], count + i, index - 1); } }