我正在尝试打印最小数量的硬币进行更改,如果不可能打印-1
在这个代码变量int [] c(coins array)中有面额,我可以用它来得出总和。
int total总计我需要使用硬币(无限供应)
public static int mincoinDP(int[] c, int total) {
int[][] a = new int[c.length + 1][total + 1];
for (int i = 0; i <= c.length; i++) {
a[i][0] = 0;
}
for (int j = 1; j <= total; j++) {
a[0][j] = Integer.MAX_VALUE - total;
}
for (int i = 1; i <= c.length; i++) {
for (int j = 1; j <= total; j++) {
if (c[i - 1] > j) {
a[i][j] = Integer.MAX_VALUE - total;
} else {
a[i][j] = Math.min(a[i - 1][j], 1 + a[i][j - c[i - 1]]);
}
}
}
return a[c.length][total];
}
对于Sum:4759和Array:{31 90 8 36}正确的输出是:59 我的输出是:60
代码有什么问题?
以下是我的递归解决方案,尝试在DP解决方案中应用相同的逻辑。这里的逻辑似乎也有些错误。对于相同的输入,它打印-2147483595
public static void main(String[] args) {
int[] array = new int[] {31, 90, 8, 36};
System.out.println(mincoin(array, 4759, 0));
}
public static int mincoin(int[] c, int total, int i) {
if (total == 0) return 0;
if (i >= c.length) return Integer.MAX_VALUE;
int x = Integer.MAX_VALUE, y = Integer.MAX_VALUE;
if (total - c[i] >= 0) {
x = 1 + mincoin(c, total - c[i], i);
}
y = mincoin(c, total, i + 1);
return Math.min(x, y);
}
编辑:代码中的问题是:
虽然我不喜欢这个版本的无限,但除此之外没有看到任何好的方法。
答案 0 :(得分:1)
看起来您正在使用动态编程,a[i][j]
旨在表示总和为j
的最小硬币数(使用前i个面额)。但我认为你的复发关系是关闭的。他们应该是:
a[0][j] = 0 if j==0, otherwise infinity
a[i][j] = a[i-1][j] if c[i-1] > j
a[i][j] = min(a[i-1][j], 1 + a[i][j-c[i-1]]) if c[i-1] <= j
主要错误是代码中的if c[i-1] > j
个案。您将值设置为无穷大(或无穷大的变体),但您应该只复制上一行中的最小硬币数,因为您可以使用较少数量的硬币构建总数。
顺便说一句,有一种更简洁的方式来编写这段代码。在伪代码中:
a = new int[total+1]
for int j = 1 to total+1 {
a[j] = infinity
}
for int coin in coins {
for j = coin to total+1 {
a[j] = min(a[j], a[j-coin]+1)
}
}
它基本上是相同的算法,但它使用较小的一维数组,它就地修改。
答案 1 :(得分:0)
以防万一有人在寻找解决方案
public int coinChange(int[] coins, int amount) {
int dp[][] = new int[coins.length+1][amount+1];
Arrays.sort(coins);
// First column of every row
for (int i = 0; i < coins.length; ++i) {
dp[i][0] = 0;
}
/*
Setting this so that this is default max value. We always
want our dp[i][j] better than this
*/
for (int j = 0; j <= amount; ++j) {
dp[0][j] = amount+1;
}
for (int i = 1; i <= coins.length; ++i) {
for (int j = 1; j <= amount; ++j) {
if (coins[i-1] > j) {
dp[i][j] = dp[i-1][j]; // Take the already best value in above row
} else {
dp[i][j] = Math.min(dp[i-1][j], 1 + dp[i][j-coins[i-1]]); // Take the best of above row and using current coin
}
}
}
if (dp[coins.length][amount] > amount) { // it means we cannot find any coin
return -1;
} else {
return dp[coins.length][amount];
}
}