322. 零钱兑换
力扣题目
给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。
你可以认为每种硬币的数量是无限的。
方法1:递归
class Solution{
int res = Integer.MAX_VALUE;
public int coinChange(int[] coins, int amount){
if (coins.length == 0){
return -1;
}
findNum(coins, amount, 0);
if (res == Integer.MAX_VALUE){
return -1;
}
return res;
}
/**
* //从大到小减到0,不等于0说明没有合适的硬币
* @param coins 硬币
* @param amount 总金额
* @param count 硬币个数
*/
public void findNum(int[] coins, int amount, int count){
if (amount < 0){
return;
}
//amount为0则说明刚刚好
if (amount == 0){
res = Math.min(res, count);
}
for (int coin : coins){
// 选择当前硬币
findNum(coins, amount - coin, count + 1);
}
}
}
方法2:记忆化搜索
class Solution{
int[] dup;//用于记录结果
public int coinChange(int[] coins, int amount){
if (coins.length == 0){
return -1;
}
dup = new int[amount];
return findNum(coins, amount);
}
public int findNum(int[] coins, int amount){
if (amount < 0){
return -1;
}
if (amount == 0){
return 0;
}
if (dup[amount - 1] != 0){
//amount - 1说明已经有结果了
return dup[amount - 1];
}
int min = Integer.MIN_VALUE;
for (int coin : coins){
int res = findNum(coins, amount - coin);
if (res >= 0 && res < min){
//amount - coin 的最少是res,amount的最少是res + 1
min = res + 1;
}
}
dup[amount - 1] = (min == Integer.MAX_VALUE) ? -1 : min;
return dup[amount - 1];
}
}
方法1:动态规划
class Solution {
public int coinChange(int[] coins, int amount) {
if (coins.length == 0){
return -1;
}
int[] dup = new int[amount + 1];
//数组赋值
Arrays.fill(dup, amount + 1);
dup[0] = 0;
for (int coin : coins){
for (int i = 0; i <= amount; i++) {
if (i - coin >= 0){
//要么没有,要么i-coin 的个数 + 1
dup[i] = Math.min(dup[i], dup[i - coin] + 1);
}
}
}
return dup[amount] == (amount + 1) ? -1 : dup[amount];
}
}