问题描述
你是一家超市的收银员,如果客人买了37元的东西,并且给了你100元,请问如何才能找到 给客人数量最少零钱,
如现有1,2,5,10,21,25 这些种类的零钱,最优的是,21,21,21 数量为3 .
思路解析
递归操作:每一次寻找可以用一张纸币去找零,如果不能够找零,则 找到所有<=该值的纸币,减去该纸币的值,再进行递归。
import time
#递归
def rec(coinValueList,change):
minCoins=change
if change in coinValueList:
return 1
else:
for i in [c for c in coinValueList if c <=change]:
numCoins =1 + rec(coinValueList,change-i)
if numCoins
minCoins=numCoins
return minCoins
t0=time.time()
x=rec([1,5,10,25,22],63)
print(x)
t1=time.time()
print("time:",t1-t0)
result:
image.png
从运行结果来看,这个递归耗时较长,因为做了过多的重复运算
2改进 使用 一个列表来存储 每一个值的最小数量的状态。
import time
def rec_ch(coinValueList,change,knownResult):
minCoins=change
if change in coinValueList:
knownResult[change]=1 #存储状态
return 1
elif knownResult[change]>0:
return knownResult[change]
else:
for i in [c for c in coinValueList if c <=change]:
numCoins =1 + rec_ch(coinValueList,change-i,knownResult)
if numCoins
minCoins=numCoins
knownResult[change]=minCoins
return minCoins
t0=time.time()
list1=[0]*64
y=rec_ch([1,5,10,25,22],63,list1)
print(y)
print(list1)
t1=time.time()
print("time:",t1-t0)
result:
image.png
3 动态规划 ,我们把2步骤的方法整理一下。
def dp(coinValueList,change,minCoins,coinUsed):
for cents in range(change+1):
coinCount=cents
newCoin = 1
for j in [c for c in coinValueList if c <=cents]:
if minCoins[cents-j]+1
coinCount=minCoins[cents-j]+1
newCoin=j
minCoins[cents]=coinCount
coinUsed[cents]=newCoin
return minCoins[change]
def printCoins(coinUsed,change):
coin=change
while coin>0:
thisCoin=coinUsed[coin]
print(thisCoin)
coin=coin- thisCoin
t0=time.time()
list1=[0]*64
coinUsed=[0]*64
y=dp([1,5,10,25,22],63,list1,coinUsed)
print(y)
#print(list1)
t1=time.time()
print("time:",t1-t0)
printCoins(coinUsed,63)
result:
image.png
参考:Python数据结构与算法分析 (布拉德利 • 米勒 戴维 • 拉努姆)