我有一个练习:
"您将获得不同面额和总金额的硬币。编写一个函数来计算构成该数量所需的最少数量的硬币。如果这笔钱不能由任何硬币组合弥补,则返回-1。"
示例1:
coins = [1, 2, 5], amount = 11
return 3 (11 = 5 + 5 + 1)
我还搜索了这样的解决方案:
public class Solution {
public int coinChange(int[] coins, int amount) {
int dp[] = new int[amount + 1];
final int INF = 0x7ffffffe;
for (int i = 1; i <= amount; i++) dp[i] = INF;
for (int i = 0; i <= amount; i++) {
for (int j = 0; j < coins.length; j++) {
if (i + coins[j] <= amount)
dp[i + coins[j]] = Math.min(dp[i + coins[j]], dp[i] + 1);
}
}
return dp[amount] == INF ? -1 : dp[amount];
}
}
我知道它关于DP,但是,我对此感到困惑,比如,dp[i + coins[j]]
的含义是什么,为什么要添加i
,以及为什么dp[i] + 1
,为什么要加1?
有人能用简单的英语表明出路吗?
答案 0 :(得分:4)
好的,让我们首先看看代码正在做什么以及它正在使用什么。 DP用于存储特定值所需的硬币数量。它按顺序执行此操作以获取值所需的硬币数量仅仅是dp&#34;的值。但是我们如何获得有序的金额列表呢?
他使用内部for循环迭代他所有的硬币,试图将硬币的值加到当前值(i)。如果小于目标金额,他会为其分配一个值。
dp[i + coins[j]] = (...)
我们知道我们的列表按值排序我们需要通过获取当前条目(i)的值加上当前硬币的值(硬币[]来获取条目的值。 J])。这是它的左侧部分。
现在正确的部分:你正在寻找可能的最小数量,这样你就可以使用Math.Min来获得n个参数中较小的一个,在这种情况下是两个。第一个参数是我们要重写的值。如果我们已经找到了表示值的非常好的方法,为什么要覆盖它呢?我们可能会意外杀死它,所以我们确保只有在找到一个比我们得到的解决方案更好的解决方案时才这样做。第二个参数只是我们需要达到当前值+ 1的硬币数量。
(...) = Math.min(dp[i + coins[j]], dp[i] + 1);
如果您还没有完全理解,可以随时询问更多细节:)