题目来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/coin-change
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题目描述
给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。
示例 1:
输入: coins = [1, 2, 5], amount = 11
输出: 3
解释: 11 = 5 + 5 + 1
示例 2:
输入: coins = [2], amount = 3
输出: -1
说明:
你可以认为每种硬币的数量是无限的。
思路
因为数选择最少的硬币数量,所以需要尽可能多的使用面额较大的硬币。由于输入的面额无序性(这一点是提交代码之后才发现的,踩坑呀。。。)。所以我们首先将面额进行排序(本文采取的由小到大排序,下标从后往前遍历)。
-
结束条件
-
amount%coins[inedx] == 0
:此时找到了累加等于amount
的面额 -
index < 0
:没有满足情况时,index会一直移动到数组前端 -
count + amount / coins[index] >= res
:硬币数量大于之前的结果res,res为目前的最优值
-
- 递归:amount
包含
n个
coins[index],从
n到
0`开始遍历
代码
int res = Integer.MAX_VALUE;
public int coinChange(int[] coins, int amount) {
if (amount == 0) {
return 0;
}
Arrays.sort(coins);
coinChange(coins, amount, coins.length - 1, 0);
return res == Integer.MAX_VALUE ? -1 : res;
}
/**
*
* @param coins 面额数组
* @param amount 金额
* @param index 当前遍历到的面额数组的下标
* @param count 使用的硬币数量
*/
private void coinChange(int[] coins, int amount, int index, int count) {
if (index < 0 || count + amount / coins[index] >= res) {return;}
if (amount % coins[index] == 0) {
res = Math.min(res, count + amount / coins[index]);
return;
}
for (int i = amount / coins[index]; i >= 0; i--) {
coinChange(coins, amount - i * coins[index], index - 1, count + i);
}
}
如有疑问,欢迎留言。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。