题目详情:
给你一个整数数组 coins
,表示不同面额的硬币;以及一个整数 amount
,表示总金额。
计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1
。
你可以认为每种硬币的数量是无限的。
示例 1:
输入:coins =[1, 2, 5]
, amount =11
输出:3
解释:11 = 5 + 5 + 1
示例 2:
输入:coins =[2]
, amount =3
输出:-1
示例 3:
输入:coins = [1], amount = 0 输出:0
提示:
1 <= coins.length <= 12
1 <= coins[i] <= 231 - 1
0 <= amount <= 104
代码实现:
class Solution { public int coinChange(int[] coins, int amount) { // 如果需要凑齐的金额为0或负数,则不需要任何硬币,直接返回0 if (amount < 1) { return 0; } // 调用私有方法,并传入一个初始化的计数数组 return coinChange(coins, amount, new int[amount]); } // 私有方法,用于递归地求解最少的硬币数量 private int coinChange(int[] coins, int rem, int[] count) { // 如果剩余金额小于0,说明当前的选择组合无法凑齐目标金额,返回-1 if(rem < 0) { return -1; } // 如果剩余金额等于0,说明已经凑齐目标金额,返回0 if (rem == 0) { return 0; } // 如果之前已经计算过当前剩余金额的最少硬币数量,则直接返回该值 if (count[rem - 1] != 0) { return count[rem - 1]; } // 初始化最少硬币数量为最大整数值 int min = Integer.MAX_VALUE; // 遍历每种硬币 for (int coin : coins) { // 递归调用,传入剩余金额减去当前硬币的面值,并更新最少硬币数量 int res = coinChange(coins, rem - coin, count); // 如果当前组合是有效的(即res大于等于0),并且比之前的组合更优(即res小于min),则更新min if (res >= 0 && res < min) { min = 1 + res; } } // 将当前剩余金额的最少硬币数量保存到计数数组中 count[rem - 1] = (min == Integer.MAX_VALUE) ? -1 : min; // 返回当前剩余金额的最少硬币数量 return count[rem - 1]; }
}