python-3.x - 递归memoization解决方案 "count changes"

标签 python-3.x algorithm coin-change

我正在尝试通过内存解决“数零钱”问题。

Consider the following problem: How many different ways can we make change of $1.00, given half-dollars, quarters, dimes, nickels, and pennies? More generally, can we write a function to compute the number of ways to change any given amount of money using any set of currency denominations?

以及使用 recursoin 的直观解决方案。

用n种硬币改变数量a的方法数等于

  1. 使用除第一种硬币以外的所有硬币来改变a的方法的数量,加上
  2. 使用所有 n 种硬币将较小的 a - d 找零的方法数,其中 d 是第一种硬币的面额。

#+BEGIN_SRC python :results output
# cache = {} # add cache 
def count_change(a, kinds=(50, 25, 10, 5, 1)):
    """Return the number of ways to change amount a using coin kinds."""
    if a == 0:
        return 1
    if a < 0 or len(kinds) == 0:
        return 0
    d = kinds[0] # d for digit
    return count_change(a, kinds[1:]) + count_change(a - d, kinds) 
print(count_change(100))
#+END_SRC
#+RESULTS:
: 292

我尽量利用内存,

Signature: count_change(a, kinds=(50, 25, 10, 5, 1))
Source:   
def count_change(a, kinds=(50, 25, 10, 5, 1)):
    """Return the number of ways to change amount a using coin kinds."""
    if a == 0:
        return 1
    if a < 0 or len(kinds) == 0:
        return 0
    d = kinds[0]
    cache[a] = count_change(a, kinds[1:]) + count_change(a - d, kinds)
    return cache[a]

它适用于像

这样的小数字
In [17]: count_change(120)
Out[17]: 494

处理大数

In [18]: count_change(11000)                        
---------------------------------------------------------------------------
RecursionError                            Traceback (most recent call last)
<ipython-input-18-52ba30c71509> in <module>
----> 1 count_change(11000)

/tmp/ipython_edit_h0rppahk/ipython_edit_uxh2u429.py in count_change(a, kinds)
      9         return 0
     10     d = kinds[0]
---> 11     cache[a] = count_change(a, kinds[1:]) + count_change(a - d, kinds)
     12     return cache[a]

... last 1 frames repeated, from the frame below ...

/tmp/ipython_edit_h0rppahk/ipython_edit_uxh2u429.py in count_change(a, kinds)
      9         return 0
     10     d = kinds[0]
---> 11     cache[a] = count_change(a, kinds[1:]) + count_change(a - d, kinds)
     12     return cache[a]

RecursionError: maximum recursion depth exceeded in comparison

内存解决方案有什么问题?

最佳答案

在内存版本中,count_change 函数必须考虑您在进行递归调用时可以使用的最高硬币指数,以便您可以使用已经计算出的值...

def count_change(n, k, kinds):
    if n < 0:
        return 0
    if (n, k) in cache:
        return cache[n,k]
    if k == 0:
        v = 1
    else:
        v = count_change(n-kinds[k], k, kinds) + count_change(n, k-1, kinds)
    cache[n,k] = v
    return v

你可以试试:

cache = {}
count_change(120,4, [1, 5, 10, 25, 50])

给出 494

同时:

cache = {}
count_change(11000,4, [1, 5, 10, 25, 50])

输出:9930221951

关于python-3.x - 递归memoization解决方案 "count changes",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58580665/

相关文章:

python - 在调试器中更改 Python 代码

algorithm - 将一张长方形的纸剪成长方形,尽量减少浪费。

python - 洗牌列表以最小化相等邻居的算法

python - 为什么第一个代码片段可以正确交换值,而第二个代码片段却不能?

python - 为什么这个求无序列表最小值和最大值的函数在某些情况下不起作用?

java - 硬币找零算法总是返回 1

硬币数量有限的硬币找零

algorithm - 确定是否可以用 N 个面额找零,每个面额只使用一次并且最多使用 k 个硬币

python - 如何将单行美化为多行?

algorithm - 面试 - 在数组中查找幅度极点