Python 递归调用函数
我有10、20、50张钞票,当我需要支付任何金额时,我需要找到最佳组合。因此,例如,当我需要支付7时,我将支付5和2的票据 我有一个函数可以计算这个。但我需要运行相同的函数3或4次,如下所示。如何递归调用该函数Python 递归调用函数,python,recursion,Python,Recursion,我有10、20、50张钞票,当我需要支付任何金额时,我需要找到最佳组合。因此,例如,当我需要支付7时,我将支付5和2的票据 我有一个函数可以计算这个。但我需要运行相同的函数3或4次,如下所示。如何递归调用该函数 my_dir={} import bisect def my_change(my_amount): c=[1,2,5,10,20,50,100,500] my_pos=bisect.bisect(c, my_amount) my_val=c[my_pos-1]
my_dir={}
import bisect
def my_change(my_amount):
c=[1,2,5,10,20,50,100,500]
my_pos=bisect.bisect(c, my_amount)
my_val=c[my_pos-1]
my_num=my_amount//my_val
my_recurr=my_amount-(my_num*c[my_pos-1])
my_dir[my_val] = my_num
return my_recurr
有没有更好的计算方法
my_change(417)
17
my_change(17)
7
my_change(7)
2
my_change(2)
0
my_dir
{2: 1, 5: 1, 10: 1, 100: 4}
更新: 根据可用的内容,组合可能会发生变化
available_cash={1:20, 2:10, 10:100, 50:100, 100:1, 500:1}
应导致以下情况:
actual_pay={1:1, 2: 3, 10: 1, 50:6, 100: 1}
更新: 有没有更好的编码方法
amt=417
my_dict={}
available_cash={1:20, 2:10, 10:100, 50:100, 100:1, 500:1}
new_list=sorted(available_cash, reverse=True)
for key in new_list:
if amt >= key * available_cash[key]:
my_dict[key] = available_cash[key]
amt = amt - (key * available_cash[key])
else:
if amt >= key:
notes = amt // key
amt = amt - (key * notes)
my_dict[key] = notes
更新1: 如果我需要在付款后找到留在ATM机上的钞票,我可以使用柜台
from collections import Counter
A = Counter(available_cash)
B = Counter(my_dict)
A - B
Counter({10: 99, 50: 94, 1: 19, 2: 7, 500: 1})
您可以使用以下内容:
my_dir = {}
change = 417
def my_change(my_amount):
# Your function code here
while change > 0:
change = my_change(change)
但实际上,您的代码可以简化,递归的解决方案是:
def my_change(amount, i=None):
c = [1, 2, 5, 10, 20, 50, 100, 500]
if i is None:
i = len(c) - 1
note = c[i]
n, rest = divmod(amount, note)
result = {}
if n > 0:
result[note] = n
if rest > 0:
result.update(my_change(rest, i - 1))
return result
不需要对分或复杂的计算。您甚至不需要使用递归,您可以在一段时间内进行换行,因此它将继续计算,直到更改为0,基本上与手动操作相同,但只需运行1次:
my_dir={}
import bisect
def my_change(my_amount):
my_dict={}
c=[1,2,5,10,20,50,100,500]
while (my_amount > 0 ):
my_pos=bisect.bisect(c, my_amount)
my_val=c[my_pos-1]
my_num=my_amount//my_val
my_recurr=my_amount-(my_num*c[my_pos-1])
my_dir[my_val] = my_num
my_amount = my_recurr
return my_dir
如果你坚持递归地做,你可以使用一个小的helper函数来做,这个函数调用自己的数量会越来越少(直到它达到零),传递自己到目前为止使用的注释集。像
import collections
notes = [500, 100, 50, 20, 10, 5, 2, 1]
def my_change(amount):
def go(amount, notesUsed):
if amount <= 0:
return notesUsed
largestNote = next(x for x in notes if x <= amount)
notesUsed[largestNote] += 1
return go(amount - largestNote, notesUsed)
return go(amount, collections.defaultdict(int))
导入集合
注=[500,100,50,20,10,5,2,1]
def my_找零(金额):
def go(金额、使用的票据):
如果数量在Python中不鼓励递归。Python不能优化递归,它限制了递归调用的最大深度(尽管这个限制可以修改)。这个特定的应用程序不会深入递归,但最好避免Python中的递归,除非它适合这个问题,例如遍历树结构
这个问题可以通过迭代很容易地解决,使用a(对于与金钱相关的任务来说有多合适:))。在每个阶段,只需删除低于当前数量的最高音符的倍数
例如:
#!/usr/bin/env python
all_notes = [1, 2, 5, 10, 20, 50, 100, 500]
def my_change(amount):
my_notes = list(all_notes)
change = {}
print amount
while amount > 0:
while my_notes[-1] > amount:
my_notes.pop()
note = my_notes[-1]
num, amount = divmod(amount, note)
print '%d x %d = %d, %d' % (num, note, num * note, amount)
change[note] = num
return change
print my_change(9)
print my_change(26)
print my_change(873)
输出
9
1 x 5 = 5, 4
2 x 2 = 4, 0
{2: 2, 5: 1}
26
1 x 20 = 20, 6
1 x 5 = 5, 1
1 x 1 = 1, 0
{1: 1, 20: 1, 5: 1}
873
1 x 500 = 500, 373
3 x 100 = 300, 73
1 x 50 = 50, 23
1 x 20 = 20, 3
1 x 2 = 2, 1
1 x 1 = 1, 0
{1: 1, 2: 1, 100: 3, 50: 1, 500: 1, 20: 1}
我在函数中添加了一些print
语句,这样您就可以了解发生了什么
my_change()
函数的核心是内置的divmod()
函数,它执行除法,将商和余数作为元组返回my_change()
还使用list.pop()
方法从my_notes
中删除过大的注释,这是所有注释列表的临时副本
可以很容易地修改此函数,将my_notes
作为参数,因此,如果由于某种原因无法使用完整的笔记集合,则可以使用此函数
问题中的代码使用对分
。这对于处理大的排序列表很好,但对于小列表来说太过分了-简单的线性搜索比对分搜索小列表要快。所以,既然您编辑了这个问题,我们就有了新的要求。
我要建议的代码比你的长一点,但它考虑到你实际上也应该修改可用的现金,因为你是从自动取款机取款的。很明显,取款会降低机器中可用的纸币数量
from collections import OrderedDict
amount = 417
available_cash = OrderedDict((
(1, 20), (2, 10), (10, 100), (50, 100), (100, 1), (500, 1)
))
def my_change(amount, available_cash):
change = {}
for note in reversed(available_cash.keys()):
note_count = amount / note
if note_count == 0:
continue
elif note_count > available_cash[note]:
note_count = available_cash[note]
available_cash[note] = 0
else:
available_cash[note] -= note_count
change[note] = note_count
amount -= note_count * note
if amount == 0:
break
return change
print my_change(amount, available_cash)
我也放弃了递归函数调用的想法。
stdlib
中的另一个重要内容是orderedict
类