当前位置: 首页 > 知识库问答 >
问题:

更改硬币的执行问题

锺离霖
2023-03-14

当我试图使用DP解决这个经典问题时,我遇到了一个实现问题。该问题给出了一组硬币,并以返回的方式进行了改变。

DP等式类似于以下内容:DP[i]=DP[i-币[j]]
其中DP[i]表示对i进行更改的方式数。

这里有一个简单的实现,这是不正确的:

int make_change_wrong(int coin[], int size, int change) {
    vector<int> DP(change + 1, 0);
    DP[0] = 1;

    for (int i = 1; i <= change; ++i) {
        for (int j = 0; j < size; ++j) {
            if (i - coin[j] >= 0 ) {
                DP[i] += DP[i - coin[j]];
            }
        }
    }

    return DP[change];
}

给定输入:int coin[]={1,5}change=6。

make_change_wrong(硬币,2,6)返回3,但2是正确的。

使用相同的逻辑,我以不那么直观的方式重新编写,并得到正确的答案:

int make_change(int coin[], int size, int change) {
    vector<int> DP(change + 1, 0);
    DP[0] = 1;

    for (int i = 0; i < size; ++i) {
        for (int j = coin[i]; j <= change; ++j) {
            DP[j] += DP[j - coin[i]];
        }
    }

    return DP[change];
}

这让我很困惑,因为对我来说,他们是一样的。。。有人能解释一下这两个实现中的问题吗?

共有3个答案

谷梁镜
2023-03-14

请尝试输入第二种方法:

coin[5] = {1,5,10,20,30};
make_change(coin,5,30);

它返回21。请检查我的测试用例。

卫胜
2023-03-14

这个问题在面试准备书《破解编码面试》中,书中给出的解决方案根本没有优化。它使用递归(不带DP)来重复计算子问题,因此运行在O(N^3)中,这尤其具有讽刺意味,因为它是动态编程章节的一部分。

下面是一个非常简单的工作解决方案(Java),它使用DP并在O(N)时间内运行。

static int numCombos(int n) {
    int[] dyn = new int[n + 1];
    Arrays.fill(dyn, 0);
    dyn[0] = 1;
    for (int i = 1;  i <= n; i++) dyn[i] += dyn[i - 1];
    for (int i = 5;  i <= n; i++) dyn[i] += dyn[i - 5];
    for (int i = 10; i <= n; i++) dyn[i] += dyn[i - 10];
    for (int i = 25; i <= n; i++) dyn[i] += dyn[i - 25];
    return dyn[n];
}
夏高朗
2023-03-14

你的第一个算法是错误的。

DP[5]=2{1,1,1,1},{5}

DP[6]=DP[5]DP[1]=3

你在数{5,1}两次。经过编辑,这样做的标准诀窍是,你可以对允许使用的面额进行计数

DP[i,m] = DP[i-coin[m],m] + DP[i,m-1]

这意味着使用[1..m]范围内的硬币改变i数量的方法的数量。很明显,你要么使用mth面额,要么不使用。

你正在使用的第二种算法是做同样的把戏,但这是一个非常聪明的方法,拿第i枚硬币,看看你能用它产生什么样的变化。这将避免过度计数,因为您避免执行类似{1,5}和{5,1}的操作。

 类似资料:
  • 所以我对编码不熟悉,我得到了一个任务,我需要做一个程序,用四分之一、一角、五分和一美分给不到一美元的零钱。然而,作业希望程序打印所需的最低硬币数量(例如,如果我输入58美分,那么输出应该是“2个25美分,1个镍和3个便士”,而不是“2个25美分,0个10美分,1个镍和3个便士”。本质上,如果没有某种硬币,那么程序就不应该打印它)。我一直在想如何制作它,这样程序就不会打印任何不必要的硬币。 这就是我

  • 我正在尝试打印最小数量的硬币来进行更改,如果不可能,请打印-1 在这段代码中,变量int[]c(硬币数组)有面额,我可以用它来计算总金额。 INT总有总和,我需要拿出使用硬币(无限供应) 对于Sum:4759和Array:{3190836},正确的输出是:59,我的输出是:60 代码中有什么错误? 下面是我的递归解决方案,尝试在DP解决方案中应用相同的逻辑。这里的逻辑似乎也有问题。对于相同的输入,

  • 具体而言,问题是: 给定面额数组<代码>硬币[],每个硬币的限制数组<代码>限制[]和数量<代码>金额,返回所需的最小硬币数量,以获取<代码>金额,或者如果不可能,返回空值。另外,用溶液中使用的每个硬币的数量填充数组 这是我的解决方案: 但它一般不起作用。 我的问题是,例如,在这种情况下: 最佳解决方案是: 并且我的算法给出作为结果。换句话说,它失败了,每当在某种情况下,我将不得不使用比可能的更少

  • 这是我关于硬币更换问题的代码,用于打印一组硬币的总方式数和目标金额 我想知道是否有任何方法可以用相同的动态规划解决方案打印这些方法(借助内部构造的表或任何其他方法) 例如,如果一组硬币是[1,3,5],目标金额是6,那么总共有4种可能的方式。[1,1,1,1,1,1,1,],[1,1,1,3],[3,3],[1,5]]我希望这种方式的列表作为输出。

  • 问题:https://leetcode.com/problems/coin-change/ 解决方案:https://repl.it/@Stylebender/HatefulAliceBlueTransverse#index.js 我理解从“按钮式”构建dp阵列解决方案的一般概念流程,但我只是想知道关于第10行: dp[i]=数学。最小值(dp[i],1 dp[i-硬币[j]]; 当你选择当前的第

  • 动态规划变更问题(有限硬币)。我正在尝试创建一个以以下内容作为输入的程序: 输出: 输出应该是大小为1的数组,其中每个单元格代表我们需要改变单元格索引量的最佳硬币数。 假设数组的单元格位于index: 5,内容为2。这意味着为了给出5(INDEX)的变化,您需要2(单元格的内容)硬币(最佳解决方案)。 基本上,我需要这个视频的第一个数组的输出(C[p])。这与有限硬币的大区别是完全相同的问题。链接