我知道有很多关于这个挑战的主题,但在标记为重复之前,请继续阅读。
需要找到所有不同的改变方法,给出一个硬币列表。 我写了一个有递归的解决方案,但效率非常低。我想添加memoization。我知道还有其他方法(例如here)来解决它,但是为了理解事情是如何运作的,我正在寻求你帮助解决我在 my 中找到的问题溶液
首先,这是代码:
# logrotate -f /etc/logrotate.d/logstash
# ls -l /usr/share/logstash/logs/
total 36
-rw-r--r-- 1 logstash logstash 17 Jan 2 10:16 logstash.log
-rw-r--r-- 1 logstash logstash 10701 Jan 2 10:16 logstash.log.1
这将返回2个解决方案,并且打印语句显示解决方案是(5,5,5,5)和(10,10)。第三种可能的解决方案(10,5,5)不包括在内,因为密钥中已有10个。
那么,如何使用唯一的方式保存一个dict来达到某个目标,而不实际跟踪所有解决方案,这会破坏目的。
感谢您的帮助。
答案 0 :(得分:1)
我认为你完全没有你的逻辑。您应该为每个金额收集解决方案。同样有意义的是同时使用n
和coins
进行记忆,同时只允许不大于当前硬币的硬币,以便不产生相同变化的排列:
from collections import defaultdict
d = defaultdict(dict)
def make_change(n, coins):
# base cases
if n < 0:
return [] # no possible solution
if n == 0:
return [[]] # one solution: empty list
# recursion
sols = [] # solutions are to be collected
# make hashable memo key, and guarantee to start with the bigger coins
tpl = tuple(sorted(coins, reverse=True))
if tpl not in d[n]:
for c in tpl:
# Only allow coins <= c for the recursion, not to get permutations
# of the same change, e.g. [10, 5] and [5, 10]
for sol in make_change(n-c, [x for x in tpl if x <= c]):
sols.append([c] + sol)
d[n][tpl] = sols
return d[n][tpl]
>>> make_change(20, [10, 5])
[[10, 10], [10, 5, 5], [5, 5, 5, 5]]
>>> make_change(25, [10, 5])
[[10, 10, 5], [10, 5, 5, 5], [5, 5, 5, 5, 5]]
>>> make_change(30, [10, 5])
[[10, 10, 10], [10, 10, 5, 5], [10, 5, 5, 5, 5], [5, 5, 5, 5, 5, 5]]
>>> make_change(27, [10, 5])
[]
答案 1 :(得分:0)
只是为了清除事情(无法评论 - 抱歉),行
c += make_change(n-i, [c for c in coins if c<=i])
允许递归中的下一个调用仅使用小于您在当前步骤中使用的硬币。如果您的硬币从最大到最小< 有序(如schwobaseggl答案),这是有道理的,否则会削减解决方案。你的情况发生了什么 - 是这样的:当计算d [10]时,因为使用的第一枚硬币是5,你就取消了使用价值10的硬币的选项,因此只得到一个改变10的解决方案 - a (5,5)改变。
为了便于调试,您应该打印整个(小)表'd',而不是在代码中间打印的所有参数。