【问题标题】:Coin change problem - brute force solution with backtracking, but how to get coins?硬币找零问题 - 带回溯的蛮力解决方案,但如何获得硬币?
【发布时间】:2018-11-28 23:43:00
【问题描述】:

我有一个带有回溯的蛮力解决方案来解决硬币找零问题。目前我得到了可以使用的最小数量的硬币。但是我怎么还能退还实际使用的硬币呢?因此,例如,如果金额是 100,那么我想返回 [25, 25, 25, 25]。

我当前的代码如下:

public class Solution {

public static void main(String[] args) {
    Solution s = new Solution();

    int coinChange = s.coinChange(0, new int[] { 1, 25, 50 }, 100);
    System.out.println(coinChange);
}

public int coinChange(int idx, int[] coins, int amount) {
    if (amount == 0){
        return 0;
    }

    if (idx < coins.length && amount > 0) {
        int maxVal = amount / coins[idx];
        int minCost = Integer.MAX_VALUE;
        for (int x = 0; x <= maxVal; x++) {
            if (amount >= x * coins[idx]) {
                int res = coinChange(idx + 1, coins, amount - x * coins[idx]);
                if (res != -1)
                    minCost = Math.min(minCost, res + x);
            }
        }
        return (minCost == Integer.MAX_VALUE) ? -1 : minCost;
    }
    return -1;
}
}

【问题讨论】:

  • 您只需要与 minCost 一起跟踪它,并更改您的 minCost 更新行,以便您知道何时更改了 minCost,然后也更新您的 minCoinsUsed。根据您的要求,您可能希望将其存储为列表,以便您可以例如当长度相同时返回多个硬币组合。
  • 实际上你的问题是关于如何将这个状态与 minCost 一起传递,因为你通过返回它来传递它?您可以通过引用 coinChange 的所有调用来传递一个对象并将状态存储在那里,或者因为您为每次搜索都有一个新的解决方案对象,您甚至可以将状态存储在其中。
  • 只需要返回一个结果。您能否通过与 minCost 一起跟踪来发布代码 sn-p 的含义?

标签: java coin-change


【解决方案1】:

首先,我建议使用准确的变量名。这将使包括您自己在内的每个人都更容易理解算法的工作原理。您当前的数组“硬币”不是硬币列表,而是可用面额的列表,因此它应该命名为“面额”或“面额_可用”或类似的名称。您称为“金额”的变量是剩余金额,因此应将其命名为“剩余”或“金额剩余”。

要存储到目前为止使用的硬币列表,您可以使用堆栈,或者只是一个被视为堆栈的列表。例如,您可以使用整数的 ArrayList。每次调用 coinChange 时,在调用之前将所选硬币的面额 (denominations[idx]) 添加到您的列表中。每次返回 -1(失败)时,在返回之前删除列表中的最后一项(如果有的话)。当达到成功条件时(amount_remaining==0),币表将包含已使用的币。

更正:由于 coinChange 在循环中被多次调用,每次调用后必须弹出堆栈,并在确定后再次推回最佳最小值。所以,它应该是这样的:

int best_coin = 0;
for (int x = 0; x <= maxVal; x++) {
    if (amount >= x * coins[idx]) {
        <<<<<< PUSH GOES HERE
        int res = coinChange(idx + 1, coins, amount - x * coins[idx]);
        <<<<<< POP GOES HERE
        if (res == -1){ 
            // failed to find valid combination of coins
        } else {
            if( minCost < res + x ){
                // do nothing
            } else { // update minimum
                minCost = res + x;
                best_coin = coins[idx];
            }
        }
    }
    <<<<<< PUSH BEST COIN
return (minCost == Integer.MAX_VALUE) ? -1 : minCost;

【讨论】:

  • 对不起,我误会了。我创建了一个静态数组列表,在递归调用 coinChange() 之前,我将 denominations[idx] 添加到该列表中。同样在返回 -1 之前,我会从列表中删除最后一个元素。我最后得到的结果如下所示:“1, 26, 26, 26, 26, 1, 26, 26, 26, 26, 1, 26, 49, 26, 26, 26, 1, 26, 26, 26, 26"
  • @donaldtbd 对,我写的不完全正确,我会更新答案
猜你喜欢
  • 2022-07-01
  • 1970-01-01
  • 2015-09-02
  • 2013-12-09
  • 2020-05-09
  • 1970-01-01
  • 2015-03-08
  • 2022-01-16
  • 1970-01-01
相关资源
最近更新 更多