【问题标题】:Coin changing using Dynamic Programming使用动态编程改变硬币
【发布时间】:2016-04-18 14:20:25
【问题描述】:

硬币兑换是一个流行的面试问题。从本质上讲,这个问题的意思是给定一组硬币面额和总数,如果每种面额硬币的供应量都是无限的,那么有多少种方法可以获得总数。

这是我的代码。 逻辑是每次我挑选硬币时,问题都会减少到解决总减去硬币的问题。

public static int numberOfWays(int total, int[] options){

        int[][] memo = new int[options.length][total+1];

        for (int i = 0; i <memo.length ; i++) {

            for (int j = 0; j <memo[i].length ; j++) {

                if(i == 0)  memo[i][j] = 1;
                else if(options[i] > j ) memo[i][j] = memo[i-1][j];
                else memo[i][j] = memo[i-1][j] + memo[i][j - options[i]];
            }
        }
        return memo[options.length-1][total];
    }

这适用于total = 5 and options = 1, 2, 3 的测试用例 但是失败了total = 10 and options = 2, 5, 3, 6

谁能帮我理解我做错了什么。

【问题讨论】:

标签: java dynamic-programming


【解决方案1】:

首先,最好写出每个数组元素代表什么的语句:

memo[i][j] 表示仅给定面额硬币options[0]options[1],...,options[i],有多少种方法可以使总金额j

现在,您似乎从中得出了一些规律:

  1. memo[0][j]1 对于所有 j
  2. 对于大于0的imemo[i][j]memo[i-1][j]相同,只要options[i] &gt; j
  3. 对于大于 0 的 imemo[i][j]memo[i-1][j] + memo[i][j - options[i]] 每当 options[i] &lt;= j

您的问题是这些法律中的第一条不正确。 (后两个是)

只有当options[0]1 时,声明“memo[0][j] 对所有1 都是j”才成立。如果options[0] 不是1,则当joptions[0] 的倍数时memo[0][j] 为1,否则为0。只使用面额硬币2,你不能赚5美分,所以你应该有(使用第二组数据)memo[0][5] == 0,但你的程序说memo[0][5] == 1。然后,这会抛出所有后续计算。

所以我会修改你的程序说:

            if(i == 0) { if (j % options[i] == 0) memo[i][j] = 1;
                         else memo[i][j] = 0; }
            else if(options[i] > j ) memo[i][j] = memo[i-1][j];
            else memo[i][j] = memo[i-1][j] + memo[i][j - options[i]];

(尽管纯粹从文体角度来看,我发现 if/else 语句即使对于单个语句也不使用大括号,但会要求错误)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多