力扣322. 零钱兑换 Java动态规划

简介: 给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,表示总金额。计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -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


二、思路讲解



以示例1为例,我们设dp[i]为目标面额i的最小钱币数,那么我们所求的就是dp[11]。假如我们知道dp[10],那么再加一个金币是dp[11]了;同理,我们如果知道dp[6],那么再加一个面额为5的金币也是dp[11]了;我们如果知道dp[9],再加一个面额为2的金币也是dp[11]了。

d9d8a17b45a440528dbe830a4a68a0ea.png


所以,dp[11] 实际上就是dp[10]+1,或者dp[9]+1,或者dp[6]+1,具体取哪个值呢?就看哪个值小,因为我们要求最小金币数。故:


min {dp[i-可能面额1], dp[i-可能面额2] , dp[i-可能面额3] ……} +1         i > 0


dp[i] =      0        i = 0


               -1       i < 0


2738454153b54edba0416cd63c93a880.png


三、Java代码实现



class Solution {
    public int coinChange(int[] coins, int amount) {
        int []dp = new int[amount+1];
        //初始化为amount+1, 便于后面min比较
        for(int i=1; i<amount+1; i++) {
            dp[i] = amount+1;
        }
        dp[0] = 0;
        //外层循环枚举所有可能的面值
        for(int i=0; i<amount+1; i++) {
            //内层循环求出该面值下所有可能选择的最小值
            for(int coin : coins) {
                //过滤掉不可能的情况
                if(i<coin) {
                    continue;
                }
                dp[i] = Math.min(dp[i], dp[i-coin]+1);
            }
        }
        return (dp[amount]==(amount+1)) ? (-1) : dp[amount];
    }
}


参考:动态规划套路详解

相关文章
|
9月前
|
机器学习/深度学习 算法 Go
【LeetCode 热题100】139:单词拆分(动态规划全解析+细节陷阱)(Go语言版)
本题是 LeetCode 热题 139:单词拆分(Word Break),需判断字符串 `s` 是否能由字典 `wordDict` 中的单词拼接而成。通过动态规划(DP)或记忆化搜索解决。DP 中定义布尔数组 `dp[i]` 表示前 `i` 个字符是否可拆分,状态转移方程为:若存在 `j` 使 `dp[j]=true` 且 `s[j:i]` 在字典中,则 `dp[i]=true`。初始条件 `dp[0]=true`。代码实现中用哈希集合优化查找效率。记忆化搜索则从起始位置递归尝试所有切割点。两种方法各有利弊,DP 更适合面试场景。思考扩展包括输出所有拆分方式及使用 Trie 优化大字典查找。
289 6
|
Python
【Leetcode刷题Python】518. 零钱兑换 II
解决LeetCode上518题“零钱兑换 II”的Python代码示例,采用动态规划方法计算构成给定总金额的不同硬币组合数。
130 2
|
12月前
|
算法 Java C++
【潜意识Java】蓝桥杯算法有关的动态规划求解背包问题
本文介绍了经典的0/1背包问题及其动态规划解法。
419 5
|
Python
【Leetcode刷题Python】322. 零钱兑换
使用动态规划解决LeetCode上322题“零钱兑换”的Python代码示例,目的是计算构成给定金额所需的最少硬币数量。
162 2
【Leetcode刷题Python】322. 零钱兑换
|
算法 Java
LeetCode(一)Java
LeetCode(一)Java
171 0
|
算法 Java
LeetCode经典算法题:矩阵中省份数量经典题目+三角形最大周长java多种解法详解
LeetCode经典算法题:矩阵中省份数量经典题目+三角形最大周长java多种解法详解
191 6
|
存储 算法 Java
LeetCode经典算法题:打家劫舍java详解
LeetCode经典算法题:打家劫舍java详解
210 2
|
人工智能 算法 Java
LeetCode经典算法题:井字游戏+优势洗牌+Dota2参议院java解法
LeetCode经典算法题:井字游戏+优势洗牌+Dota2参议院java解法
197 1
|
存储 算法 Java
LeetCode经典算法题:预测赢家+香槟塔java解法
LeetCode经典算法题:预测赢家+香槟塔java解法
212 1
|
缓存
力扣每日一题 6/14 动态规划+数组
力扣每日一题 6/14 动态规划+数组
129 1