用硬币找零的组合数

时间:2019-02-08 20:33:19

标签: python-3.x

我们有不同数量的无限制硬币-计算这些硬币如何构成特定数量的独特组合。例如:

n = 4(例如4美分)

coins_list = [1,2]-我们有1美分硬币和2美分硬币 不同的组合是112、1111和22。(应该排除121和211,因为它们不是唯一的-使用一个2美分硬币和两个1美分硬币)

我已经观看了以下视频:https://www.youtube.com/watch?v=k4y5Pr0YVhg 无数次,并且编辑了无数次代码,但我无法摆脱不同订单的相同组合。

 def make_change(n, coinlist_index=None):
    coin_list = [1, 2]

    if coinlist_index == None: 
        coinlist_index = 0  
#coin index position in coin_list; starts at index 0 and cycles through all the coins

    if n == 0:
        return 1

    if n < 0:
        return 0

    ways = 0

    # if I use for i in range(len(coin_list)), it returns an error message saying that index is out of range
    for coinlist_index in range(len(coin_list)):
        ways += make_change((n - coin_list[coinlist_index]), coinlist_index)
        coinlist_index += 1

    return ways

make_change(4)

输出: 5

我的输出是5(用1美分硬币和2美分硬币进行4美分兑换的不同方法),而不是3(这是我想要的)。

我确定它与for循环到底有关,但是当我将“ for range的coinlist_index ...”更改为另一个迭代器时,我得到一个错误,指出索引超出范围

发生了什么,更重要的是,我该如何解决?

编辑:PS这只是我要解决实际分配的一个简单示例-包含6种类型的硬币(以美分(1、5、10、25、50、100)为单位),并计算制作多少种方法换200美元。我已经看到并尝试了动态编程方法,该方法行得通,但是我们必须使用递归进行分配。

2 个答案:

答案 0 :(得分:0)

我认为5实际上是正确的答案。

1 1 1 1
1 1 2
1 2 1
2 1 1
2 2

或者,如果要获得不同的结果,可以将结果存储在列表中,然后删除重复的结果。

def make_change(n, coinlist_index=0):
    coin_list = [1, 2]

    if n == 0:
        return [[]]

    if n < 0:
        return []

    ways = []

    for coinlist_index in range(len(coin_list)):
        res = make_change((n - coin_list[coinlist_index]), coinlist_index)
        ways += list(map(lambda x : x + [coin_list[coinlist_index]], res))

    return ways

def remove_dup(lolist):
    res = []
    for lst in lolist:
        lst.sort()
        if lst not in res:
            res.append(lst)
    return res

print remove_dup(make_change(4))

答案 1 :(得分:0)

好像我可以正常工作了。在每个递归遍历中,您都希望确保您不会重复计算进行更改的可能方法。我这样做的目的是确保您永远不会在coin_list中倒退。因此,对于coin_list [1,2],如果我们曾经使用过2美分的硬币,那么我们永远都不希望以后再使用1美分的硬币。我通过稍微更改for循环来确保遵循此顺序:

for i in range(len(coin_list)-coinlist_index):
    ways += make_change((n - coin_list[i+coinlist_index-1]), coinlist_index)

在for循环中,我从上限减去了coinlist_index,因此一旦索引达到1,我们就不会循环遍历所有硬币,然后将索引添加到您从coin_list中拉出的位置,确保一旦coinlist_index为1或更大,我们从不使用coin_list [0]。这使我在您的示例案例中达到3,希望它适用于所有案例。完整代码:

def make_change(n, coinlist_index=None):
    coin_list = [1, 2]

    if coinlist_index == None: 
        coinlist_index = 0  
#coin index position in coin_list; starts at index 0 and cycles through all the coins

    if n == 0:
        return 1

    if n < 0:
        return 0

    ways = 0

    # if I use for i in range(len(coin_list)), it returns an error message saying that index is out of range
    for i in range(len(coin_list)-coinlist_index):
        ways += make_change((n - coin_list[i+coinlist_index-1]), coinlist_index)
        coinlist_index += 1

    return ways

print(make_change(4))