零钱兑换(Coin Change)java
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhangjingao/article/details/82966587
题干
给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。
示例 1:
输入: coins = [1, 2, 5], amount = 11
输出: 3
解释: 11 = 5 + 5 + 1
示例 2:
输入: coins = [2], amount = 3
输出: -1
说明:
你可以认为每种硬币的数量是无限的。
分析
这题是一道动态规划题。那么我们来找状态转移方程。
来个比较接地气的解释。 首先我们来想一下,我们大脑在遇见这种题的时候是怎么思考的,以示例1举例。coins={1,2,5},当amount=1,2,5时,我们直接就能看到需要一个硬币即可。当amount=6时呢,我们会首先想,
1. 先用硬币面额为1的硬币,然后减去1剩5,那组成5的最少需要多少硬币呢?前面看到了是1,那么就是答案是2;
2. 用面额为2的硬币,然后6-2=4,组成4所需的最少硬币块数是2块(2+2),那么就是3。
3. 用面额为5的硬币,然后6-5=1,组成1所需的最少硬币就是1块,那么答案就是2;
那么转换为程序的话就是首先定义一个数组ans[amount+1],存放amount=i时的最少硬币块数。然后对i=1-amount循环,然后再对硬币面额 j=0-coin.length循环,依次比较用每个硬币面额时的最小硬币块数。
(其实这题不难,解释那么多太详细了,,,,)
代码
public int coinChange(int[] coins, int amount) {
//初始化答案数组
if( amount == 0 ){
return 0;
}
int [] ans = new int[amount+1];
for( int i = 0 ; i < coins.length ; ++i){
if( coins[i] > amount ){
continue;
}
ans[coins[i] ] = 1;
}
for( int i = 1 ; i <= amount ; ++i ){
//已经初始化过
if( ans[i] != 0 ){
continue;
}
//mi用来保存临时最小值
int mi = Integer.MAX_VALUE;
for( int j = 0 ; j < coins.length ; ++j ){
//上一次的面额不合法
if( i - coins[j] <= 0 || ans[ i - coins[j] ] == 0 ){
continue;
}
mi = Math.min( mi , ans[i - coins[j] ] + 1);
}
mi = mi == Integer.MAX_VALUE ? 0 : mi ;
ans[i] = mi;
}
return ans[amount] == 0 ? -1 : ans[amount];
}