简体   繁体   English

最少需要多少硬币才能找零

[英]minimum number of coins to make change

I am trying to print the minimum number of coins to make the change, if not possible print -1我正在尝试打印最小数量的硬币来进行更改,如果不可能打印 -1

In this code variable int[] c (coins array) has denominations I can use to come up with Total sum.在这段代码中,变量 int[] c(硬币数组)有我可以用来计算总和的面额。

int total has total sum I need to come up with using coins (Unlimited supply) 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];
    }

For Sum : 4759 and Array: {31 90 8 36} Correct output is: 59 My output is: 60对于总和:4759 和数组:{31 90 8 36} 正确的输出是:59 我的输出是:60

What is wrong in code ?代码有什么问题?

Below is my recursive solution, trying to apply same logic in DP solution.下面是我的递归解决方案,尝试在 DP 解决方案中应用相同的逻辑。 Something seems to be wrong in logic here as well.这里的逻辑似乎也有问题。 For same input it prints -2147483595对于相同的输入,它打印 -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:编辑:代码中的问题是:

  1. DP version: if (c[i -1] > j) , It is case when solution is not possible choosing this coin: Here we should accept solution without this coin which is a[i-1][j] DP 版本: if (c[i -1] > j) ,这是不可能选择这个硬币的解决方案的情况:这里我们应该接受没有这个硬币的解决方案,即 a[i-1][j]
  2. Recursive version: if(i >= c.length), it is terminating condition when we dont any coin at this position, here we should return infinity (Integer.MAX_VALUE) and to avoid integer overflow return Integer.MAX_VALUE - total.递归版本:if(i >= c.length),当我们在这个位置没有任何硬币时它是终止条件,这里我们应该返回无穷大(Integer.MAX_VALUE)并避免整数溢出返回Integer.MAX_VALUE - total。

Though I dont like this version of infinity, but dont see any nice way other than this here.虽然我不喜欢这个版本的无穷大,但在这里看不到除此之外的任何好方法。

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 .看起来您正在使用动态编程, a[i][j]旨在表示总和为j的最小硬币数量(使用前 i 个面额)。 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.主要错误是代码中的if c[i-1] > j情况。 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.它本质上是相同的算法,但它使用了一个较小的一维数组,它可以就地修改。

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];
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM