给你一个整数数组 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
示例 4:
输入:coins = [1], amount = 1 输出:1
示例 5:
输入:coins = [1], amount = 2 输出:2
提示:
1 <= coins.length <= 12
1 <= coins[i] <= 231 - 1
0 <= amount <= 104
emmm动态规划,一开始想写一个从面值大的开始优先使用,依次递减取余,这种方法来处理,但是逻辑没有理太清楚,代码写的非常复杂,最后放弃了。
还是来看动态规划
class Solution {
public int coinChange(int[] coins, int amount) {
Arrays.sort(coins);
if ( amount==0 ){
return 0;
}
if (amount < coins[0] ){
return -1;
}
int[] dp = new int[amount+1];
Arrays.fill(dp,-1);
int i = 1;
while (i <= amount){
for (int coin : coins) {
if (i < coin){
break;
}
if (i == coin){
dp[i] = 1;
break;
}else {
if (dp[i-coin] == -1){
continue;
}
if (dp[i] == -1){
dp[i] = dp[i-coin]+1;
}else {
dp[i] = Math.min(dp[i],dp[i-coin]+1);
}
}
}
i++;
}
return dp[amount];
}
}
以实际举例来说 [1, 2, 5]的常规面值
如果需要的面值是0,则0个,这个没有疑问
如果目标面值是1,因为直接有一个面值为1的,所以结果是F(1) = 1
如果目标面值是2,因为直接有一个面值是2的硬币,所以结果是F(2) = 1个。但是面值2的情况可以由面值1的值1个加上一枚1元的组合而成,需要两枚硬币。但是这边的两枚大于之前的1,所以丢弃这个结果,当有硬币面值直接相等的时候就可以直接用1枚。
当面值为3的时候,可以由F(1)加上1枚面值为2的或者F(2)加上1枚面值为1的均为2。当然我们知道面值为3的可以用3枚面值1的硬币组成,这个组合对应为之前求F(2)时候的非最小值情况的两枚面值1的硬币,加上凑到3需要的额外一枚硬币组合而成。
当面值为4的时候,可以由F(3)加上一个面值1硬币或者F(2)加上一个面值2硬币而来。同样的更多其他的组合都不是最优解了。
当面值为5的时候,有面值5的硬币,直接F(5) = 1。
往后递推类似,如果有直接面额的相等的,则直接返1,如果没有,则考虑距离最近的最优解额外加一个硬币的面值的情况。
发表评论