使用递归构成金额的最小硬币数

时间:2017-09-29 16:16:38

标签: python recursion optimization

问题是用于说明动态编程的流行问题,如下所示。我们拥有每种面值1,3和5的无限硬币。我们希望最小数量的硬币获得金额N.

我知道动态编程方法,我们从基础案例中构建解决方案。但我想看看如何编写纯粹的递归解决方案。对于N = 11和面额= [1,3,5],我能够轻松地手工完成。但出于某种原因,我无法完成以下工作。

    def minNumberOfCoins(amount, denominations):
        if amount <= 0:
            return(0)
        if amount in denominations:
            return(1)
        else:
            listToExamine = list(filter(lambda x: x > 0, map(lambda x: amount - x, denominations)))
            print(listToExamine)
            minVal = min(listToExamine, key=lambda x: 1 + minNumberOfCoins(x, denominations))
            return(minVal)

据我所知,逻辑与我在纸上所做的相同。 Python的递归中是否存在一些我不知道的细微差别,或者是否存在一些我遗漏的微妙内容?谢谢!

2 个答案:

答案 0 :(得分:1)

这种实现似乎更直接:

def minNumberOfCoins(amount, denominations):

    if amount <= 0:
        return(0)

    if amount in denominations:
        return(1)

    for d in sorted(denominations, reverse=True):
        if d <= amount:
            return 1 + minNumberOfCoins(amount - d, denominations)

答案 1 :(得分:1)

更具可读性的方法。你不应该将mapfilter与lambdas混在一起。条件理解和生成器通常是更好的选择:

def min_coins(amount, denominations):
    # these two base cases seem to cover more edge cases correctly
    if amount < 0:
        return None
    if amount == 0:
        return 0
    tries = (min_coins(amount-d, denominations) for d in denominations)
    try:
        return 1 + min(t for t in tries if t is not None)
    except ValueError:  # the generator in min produces no values
        return None   

min_coins(11, [1,3,5])
# 3
相关问题