Reputation: 5233
I am trying to print the minimum number of coins to make the change, if not possible print -1
In this code variable int[] c (coins array) has denominations I can use to come up with Total sum.
int total has total sum I need to come up with using coins (Unlimited supply)
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];
}
For Sum : 4759 and Array: {31 90 8 36} Correct output is: 59 My output is: 60
What is wrong in code ?
Below is my recursive solution, trying to apply same logic in DP solution. Something seems to be wrong in logic here as well. For same input it prints -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);
}
Edit: Problems in code were:
Though I dont like this version of infinity, but dont see any nice way other than this here.
Upvotes: 0
Views: 1275
Reputation: 167
Just in case someone looking for solution
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];
}
}
Upvotes: 0
Reputation: 58349
It looks like you're using dynamic programming, with a[i][j]
intended to represent the minimum number of coins (using the first i denominations) that sum to j
. But I think your recurrence relations are off. They should be:
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
The main mistake is the if c[i-1] > j
case in your code. You set the value to infinity (or your variant of infinity), but you should just copy the minimum number of coins from the previous row since you may be able to construct the total using the smaller number of coins.
By the way, there is a neater way to write this code. In pseudocode:
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)
}
}
It's essentially the same algorithm, but it uses a smaller one-dimensional array which it modifies in-place.
Upvotes: 1