如果每枚硬币的数量是无限的,那么复杂性是O(n*m),其中n
是总变化,m
是硬币类型的数量。现在,当每种类型的硬币都受到限制时,我们必须考虑剩余的硬币。我设法使它与O(n*m2)
的复杂性使用另一个大小的n
,所以我可以跟踪每个类型的剩余硬币。有没有一种方法可以让复杂性变得更好?编辑:问题是计算进行精确给定更改所需的最少硬币数量以及我们使用每种硬币类型的次数
下面是Python中O(nm)解决方案的实现。
如果定义C(C,k)=1x^cx^(2c)。。。x^(kc)
,然后程序计算多项式乘积(C(C[i],k[i]),i=1…ncoins)的第一个
n1
系数。此多项式的j
第个系数是对j
进行更改的方法数。
当所有的
k
s不受限制时,该多项式乘积易于计算(例如,请参见:https://stackoverflow.com/a/20743780/1400793)。当受到限制时,需要能够有效地计算k
项的运行和,这是在程序中使用rs
数组完成的。
# cs is a list of pairs (c, k) where there's k
# coins of value c.
def limited_coins(cs, n):
r = [1] + [0] * n
for c, k in cs:
# rs[i] will contain the sum r[i] + r[i-c] + r[i-2c] + ...
rs = r[:]
for i in xrange(c, n+1):
rs[i] += rs[i-c]
# This line effectively performs:
# r'[i] = sum(r[i-j*c] for j=0...k)
# but using rs[] so that the computation is O(1)
# and in place.
r[i] += rs[i-c] - (0 if i<c*(k+1) else rs[i-c*(k+1)])
return r[n]
for n in xrange(50):
print n, limited_coins([(1, 3), (2, 2), (5, 3), (10, 2)], n)
不需要额外的循环。您需要:
下面是Python 3中代码的外观:
def getChange(coins, amount, coinIndex = 0):
if amount == 0:
return [] # success
if coinIndex >= len(coins):
return None # failure
coin = coins[coinIndex]
coinIndex += 1
# Start by taking as many as possible from this coin
canTake = min(amount // coin["value"], coin["count"])
# Reduce the number taken from this coin until success
for count in range(canTake, -1, -1): # count will go down to zero
# Recurse to decide how many to take from the next coins
change = getChange(coins, amount - coin["value"] * count, coinIndex)
if change != None: # We had success
if count: # Register this number for this coin:
return change + [{ "value": coin["value"], "count": count }]
return change
# Example data and call:
coins = [
{ "value": 20, "count": 2 },
{ "value": 10, "count": 2 },
{ "value": 5, "count": 3 },
{ "value": 2, "count": 2 },
{ "value": 1, "count": 10 }
]
result = getChange(coins, 84)
print(result)
给定示例的输出:
[
{'value': 1, 'count': 5},
{'value': 2, 'count': 2},
{'value': 5, 'count': 3},
{'value': 10, 'count': 2},
{'value': 20, 'count': 2}
]
如注释中所述,上述算法返回其找到的第一个解决方案。如果有一个要求,即当存在多个解决方案时,单个硬币的数量必须最小化,那么您不能在循环的一半返回,而是必须保留迄今为止找到的“最佳”解决方案。
以下是为实现此目的而修改的代码:
def getchange(coins, amount):
minCount = None
def recurse(amount, coinIndex, coinCount):
nonlocal minCount
if amount == 0:
if minCount == None or coinCount < minCount:
minCount = coinCount
return [] # success
return None # not optimal
if coinIndex >= len(coins):
return None # failure
bestChange = None
coin = coins[coinIndex]
# Start by taking as many as possible from this coin
cantake = min(amount // coin["value"], coin["count"])
# Reduce the number taken from this coin until 0
for count in range(cantake, -1, -1):
# Recurse, taking out this coin as a possible choice
change = recurse(amount - coin["value"] * count, coinIndex + 1,
coinCount + count)
# Do we have a solution that is better than the best so far?
if change != None:
if count: # Does it involve this coin?
change.append({ "value": coin["value"], "count": count })
bestChange = change # register this as the best so far
return bestChange
return recurse(amount, 0, 0)
coins = [{ "value": 10, "count": 2 },
{ "value": 8, "count": 2 },
{ "value": 3, "count": 10 }]
result = getchange(coins, 26)
print(result)
输出:
[
{'value': 8, 'count': 2},
{'value': 10, 'count': 1}
]
我在理解动态规划中的硬币兑换问题时遇到了一个小问题。简单地说,我必须用最少数量的硬币来兑换一笔钱。 我有n种面值为1=v1的硬币
我试图自己解决LeetCode问题322。硬币兑换: 您将获得一个整数数组,表示不同面额的硬币,以及一个整数金额,表示总金额。 返回您需要的最少数量的硬币,以弥补该金额。如果这些硬币的任何组合都无法弥补这一数额,则返回-1。 你可以假设每种硬币的数量是无限的。 我似乎有一个错误,无法找出它。 我用DFS解决,基本上是说当目标达到0时,只需将所有的聚集在一个数组中,并动态地保持尽可能短的结果。这是问
在硬币系统C={c1,c2,…ck}中,应改变给定的数量x,以使每个硬币ci具有给定的重量wi。我们想计算可能变化的总重量。两种变化是不同的,如果他们包含在不同的顺序相同的硬币。 如何给出上述问题的动态规划递归?我知道最小硬币兑换问题的递归(即C(x)=min{C(x-C)1 for x
我编写的代码使用动态规划解决了基本的硬币兑换问题,并给出了进行兑换所需的最小硬币数量。但是我想把每个硬币的数量存储在最小的数字里。 我试图做的是初始化数组,就像散列一样,只要找到,它就会增加的数量,即。但这并不是我想要的方式,因为它每次发现对应于时都会添加硬币。因此,在最终答案中,数字不是硬币的最终计数。 代码如下:
但是我们不能这样做吗:(是给定的可用硬币的排序集,和是它的下标,是给定的最高价值硬币) 我写的东西有什么问题吗?虽然解决方案不是动态的,但不是更有效吗?
我一直在使用动态规划研究硬币兑换问题。我尝试制作一个数组fin[],其中包含索引所需的最小硬币数,然后打印它。我已经写了一个代码,我认为应该给出正确的输出,但我不明白为什么它没有给出准确的答案。例如:对于输入:4 3 1 2 3(4是要更改的金额,3是可用硬币的类型,1 2 3是硬币值列表)输出应该是:0 1 1 2(因为我们有1,2,3作为可用硬币,需要0个硬币更改0,1个硬币更改1,1个硬币更