力扣经典算法篇-52-零钱兑换(动态规划)
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、最后的元素为结果
规律:
要对一个新的值,要校验这组硬币能否满足组合目标价值的情形,需要遍历这个硬币的集合。
校验某一个硬币时,需要减去当前硬币的价值,验证减去后的值是否满足调价,如果满足条件,该硬币需要校验,否则直接跳过。
代码示例:
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!!!