赞
踩
给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,表示总金额。
计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1 。
你可以认为每种硬币的数量是无限的。
硬币数量无限,有面额,金额是固定的,最少多少种凑法,感觉有点类似背包问题,在物品数量无限的情况下,给出物品大小,背包大小,有多少种装法。但这里是最少物品数量,不考虑物品种类数,所以定义dp数组时,试着直接忽略种类这个维度。
定义dp数组,dp[j]
代表在大小为j
的情况下,最少花费了dp[j]
个硬币。
考虑状态转移方程
i
种硬币,为了使得总硬币数最少,我们只取1枚,dp[j] = dp[j-第i种硬币的面额]+1
dp[j] = dp[j]
amount
的情况下,最多需要amount
枚,加个常数即代表最大值。public int coinChange(int[] coins, int amount) {
if(amount==0)
return 0;
int[] dp = new int[amount+1];
Arrays.fill(dp,amount+1);
dp[0] = 0;
for(int i=0;i<amount+1;i++){
for(int coin:coins){
if(i-coin>=0)
dp[i] = Math.min(dp[i],dp[i-coin]+1);
}
}
return dp[amount]==amount+1?-1:dp[amount];
}
给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。
请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。
假设每一种面额的硬币有无限个。
题目数据保证结果符合 32 位带符号整数。
无限硬币,硬币有面值,有限金额,可以想到,有限大小的背包,去装一堆不限量的物品,每个物品有着相应的大小,问有多少种正好装满的装法。
所以,可以借鉴背包问题的dp数组设置方法,设dp[i][j]
代表在使用i种硬币,达到j金额的情况下,有dp[i][j]
种装法。
下面考虑状态转移方程,这个问题里,能做选择的是装不装第i种硬币,所以方程如下:
dp[i][j]
还是之前的结果dp[i-1][j]
dp[i][j]
则得加上装的装法,即dp[i][j] = dp[i-1][j] + dp[i][j-第i种硬币的面值]
接下来,考虑边界条件
一开始,
dp[0][j]=0
dp[i][0]=1
public int change(int amount, int[] coins) { int len = coins.length; int[][] dp = new int[len+1][amount+1]; for(int i=0;i<=len;i++) dp[i][0]=1; for(int i=1;i<=len;i++){ for(int j=1;j<=amount;j++){ if(j-coins[i-1]>=0){ dp[i][j] = dp[i-1][j] + dp[i][j-coins[i-1]]; }else{ dp[i][j] = dp[i-1][j]; } } } return dp[len][amount]; }
//空间压缩
public int change(int amount, int[] coins) {
int len = coins.length;
int[] dp = new int[amount+1];
dp[0] = 1;
for(int i=1;i<=len;i++)
{
for(int j=1;j<=amount;j++){
if(j-coins[i-1]>=0)
dp[j] = dp[j]+dp[j-coins[i-1]];
}
}
return dp[amount];
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。