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

硬币兑换的复杂性有限

陈博容
2023-03-14

如果每枚硬币的数量是无限的,那么复杂性是O(n*m),其中n是总变化,m是硬币类型的数量。现在,当每种类型的硬币都受到限制时,我们必须考虑剩余的硬币。我设法使它与O(n*m2的复杂性使用另一个大小的n,所以我可以跟踪每个类型的剩余硬币。有没有一种方法可以让复杂性变得更好?编辑:问题是计算进行精确给定更改所需的最少硬币数量以及我们使用每种硬币类型的次数

共有2个答案

浦出野
2023-03-14

下面是Python中O(nm)解决方案的实现。

如果定义C(C,k)=1x^cx^(2c)。。。x^(kc),然后程序计算多项式乘积(C(C[i],k[i]),i=1…ncoins)的第一个n1系数。此多项式的j第个系数是对j进行更改的方法数。

当所有的ks不受限制时,该多项式乘积易于计算(例如,请参见: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)

燕永昌
2023-03-14

不需要额外的循环。您需要:

  • 递归深度最多为m(硬币数量)级别,每个递归级别处理一个特定硬币

下面是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个硬币更