查找所有排列以获得给定的总和(硬币找零问题)
Posted
技术标签:
【中文标题】查找所有排列以获得给定的总和(硬币找零问题)【英文标题】:Finding all permutations to get the given sum (Coin change problem) 【发布时间】:2020-11-29 11:17:37 【问题描述】:我正在尝试解决一个经典的硬币找零(动态)问题。 为了使用动态方法找到所有唯一组合的数量以从无限面额的硬币中求和,我使用了这种方法:
/*
n - number of coins
arr[] - coin denominations
x - total sum
dp[] - array to store number of combinations at index i.
*/
for (int j = 0; j < n; j++)
for (int i = 1; i <= x; i++)
if (arr[j] <= i)
dp[i] = (long) ((dp[i] + dp[i - arr[j]]) % (1e9 + 7));
这给了我所有可能的独特combinations
计数:
例如:
Input:
n=3 x=9
Coins: 2 3 5
Output:
3
到目前为止,一切都很好。
但我观察到,只需交换上面 sn-p 中的循环,我就能得到所有可能的 permutations
。
for (int i = 1; i <= x; i++)
for (int j = 0; j < n; j++)
if (arr[j] <= i)
dp[i] = (long) ((dp[i] + dp[i - arr[j]]) % (1e9 + 7));
这给了我所有可能的独特permutations
计数:
例如:
Input:
3 9
2 3 5
Output:
8
通过调试和每次迭代,我映射了一个已形成的模式,但不明白为什么我得到排列的原因。 任何人都可以迭代地向我解释这一点。任何帮助将不胜感激。 谢谢
这两个问题都可以在这里找到:
排列:Coin Combinations 1 组合:Coin Combinations 2【问题讨论】:
【参考方案1】:第一个带有硬币外循环的代码在每一轮外循环中更新了用新硬币组成值dp[]
的方法数。因此,在第 k 轮之后,我们有 dp[]
数组仅填充了 k
硬币的组合,其余硬币尚未使用。如果我们为有序硬币数组存储组合本身,我们将只看到像1 1 5
这样的有序组合,而 5 永远不会排在 1 之前。这就是组合的原因。
第 m 轮外循环的第二个代码使用所有可能的硬币填充第 m 个单元格dp[m]
。所以我们计算 m=7
1 1 5
和 1 5 1
和 5 1 1
变体。这就是为什么这里计算所有排列的原因。
另外评论:我们可以制作二维数组,其中dp[x][c]
包含排列数,总和为x
,以硬币a[c]
结尾。请注意,在这种情况下,我们必须将排列计数与 sum x-a[c]
连接起来。供参考 - 1d 和 2d Python 代码。
def coins1(a, n): #permutations
count = [1]+[0]*n
for x in range(1, n + 1):
for c in a:
if (x-c >= 0):
count[x] += count[x-c]
return count[n]
def coins11(a, n): #permutations 2d
m = len(a)
count = [[1] + [0]*(m-1)] + [[0]*m for i in range(n)]
for x in range(1, n + 1):
for c in range(m):
if x>=a[c]:
count[x][c] += sum(count[x-a[c]])
return sum(count[n])
【讨论】:
非常感谢!只是一个后续的疑问。我为组合问题创建了二维数组,然后将其优化为一维数组。但是在对排列做同样的事情时,我不知道在二维数组中为每一行放入什么?二维数组版本也可以用于排列吗?以上是关于查找所有排列以获得给定的总和(硬币找零问题)的主要内容,如果未能解决你的问题,请参考以下文章