1、题干
给你一个整数数组 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
2、解题
方法一:(动态规划)
本题为求取最优值的问题,可以使用贪心或动态规划的算法策略。对于本题,贪心无法获取全局最优的结果,需要使用动态规划的思路。
动态规划的步骤:
1、定义数组
2、初始化赋值
3、找规律
4、对之后的元素赋值
5、最后的元素为结果
规律:
要对一个新的值,要校验这组硬币能否满足组合目标价值的情形,需要遍历这个硬币的集合。
校验某一个硬币时,需要减去当前硬币的价值,验证减去后的值是否满足调价,如果满足条件,该硬币需要校验,否则直接跳过。
代码示例:
java
import java.util.Arrays;
public class Test60 {
public static int coinChange(int[] coins, int amount) {
// 定义数组
int[] dp = new int[amount + 1];
Arrays.fill(dp, Integer.MAX_VALUE);
// 初始化赋值
dp[0] = 0;
// 遍历,后续数据进行赋值
for (int i = 1; i < amount + 1; i++) {
// 遍历硬币的列表,验证每一种可能情况,注意不能截断
for (int j = 0; j < coins.length; j++) {
int coinValue = coins[j];
if (coinValue == i) {
// 如果等值,只要1个硬币即可,快速截断
dp[i] = 1;
break;
} else if (coinValue < i) { // 只有当硬币价值小于总价值时,才存在逻辑可能,进行校验。
// 减去当前硬币价值时,如果存在值,则可以存在结果
if (dp[i - coinValue] != Integer.MAX_VALUE) {
// 因为10元可以由2个5元拼凑,也可以由10个1元拼凑,所以需要遍历每一种组合的可能,并取较小值
dp[i] = Math.min(dp[i], dp[i - coinValue] + 1);
}
}
}
}
// Integer.MAX_VALUE为不可能的情况,注意
return dp[amount] == Integer.MAX_VALUE ? -1 : dp[amount];
}
public static void main(String[] args) {
int[] coins = {1, 2, 5};
int amount = 11;
System.out.println(coinChange(coins, amount));
}
}
向阳前行,Dare To Be!!!