递归树过早终止功能

时间:2017-12-03 11:58:02

标签: python recursion

我正在尝试定义一个函数,该函数返回合法硬币的所有组合的列表,这些组合相当于给定的金额。假设给定的金额 10 且合法金币 5,2,3 。在这种情况下,函数应该返回:

[[2, 2, 2, 2, 2], [3, 3, 2, 2], [5, 3, 2], [5, 5]]

我设法创建了一个递归函数,它给了我正确的结果,但是通过在单独的行上打印正确的答案并混合在一堆None中。

如何在不过早终止功能的情况下将正确答案返回到合法解决方案列表中。我知道我的功能无效。我自己可以考虑一些改进,并将在以后实施。

这是我的代码:

def count_change(tot_amount, coins, used_coins=[]):

    # Sort coins and get rid of coins that are too big
    if len(used_coins) == 0:
        coins = [x for x in sorted(coins) if x <= tot_amount]

    for coin in coins:
        # If the first condition holds I want to add the printed
        # statement to a list of solution instead of printing
        if tot_amount - sum(used_coins) == coin:
            print(used_coins + [coin])
        elif tot_amount - sum(used_coins) > coin:
            print(count_change(tot_amount,
                               [x for x in coins if x <= coin],
                               used_coins + [coin]))

print(count_change(10, [5, 2, 3]))

这是输出:

[2, 2, 2, 2, 2]
None
None
None
None
None
None
None
[3, 3, 2, 2]
None
None
None
None
None
None
[5, 3, 2]
None
[5, 5]
None
None

1 个答案:

答案 0 :(得分:1)

您只需将print调用替换为yield即可将您的功能转换为generator

我还将used_coins的默认值更改为None,因为您实际上并不想在此处使用默认的可变参数。有关详细信息,请参阅“Least Astonishment” and the Mutable Default Argument

def count_change(tot_amount, coins, used_coins=None):
    # Sort coins and get rid of coins that are too big
    if used_coins is None:
        used_coins = []
        coins = [x for x in sorted(coins) if x <= tot_amount]

    for coin in coins:
        # If the first condition holds we have a valid combination 
        if tot_amount - sum(used_coins) == coin:
            yield used_coins + [coin]
        # Otherwise, if this coin is small enough, recurse to find combinations
        # that use this coin in addition to the existing used_coins
        elif tot_amount - sum(used_coins) > coin:
            yield from count_change(tot_amount,
                               [x for x in coins if x <= coin],
                               used_coins + [coin])

for t in count_change(10, [5, 2, 3]):
    print(t)

<强>输出

[2, 2, 2, 2, 2]
[3, 3, 2, 2]
[5, 3, 2]
[5, 5]

如果确实需要解决方案列表,那么只需将生成器运行到列表中,如下所示:

seq = list(count_change(10, [5, 2, 3]))
print(seq)

<强>输出

[[2, 2, 2, 2, 2], [3, 3, 2, 2], [5, 3, 2], [5, 5]]