Python递归 - 找零钱
特殊的方法-循环:
#无法解决某些情况,例如存在21元的零钱
def fun(n):
count = 0
while n > 25:
n = n - 25
count = count + 1
while n > 10:
n = n - 10
count = count + 1
while n > 5:
n = n - 10
count = count + 1
while n > 0:
n = n - 1
count = count + 1
return count
print(fun(63))
特殊的方法 - 递归:
def fun(n): # 分好类
if n <= 0:
return 0
elif n >= 25:
return 1 + fun(n-25)
elif n >= 10:
return 1 + fun(n-10)
elif n >= 5:
return 1 + fun(n-5)
elif n >= 1:
return 1 + fun(n-1)
print(fun(25))
递归 + 记忆:
import time
def recMD(valueList, change, Knowlist):
minNum = change
if change in valueList: # 可以作为结束条件
Knowlist[change] = 1
return 1
elif Knowlist[change] > 0: # 回忆
return Knowlist[change]
else:
for i in [c for c in valueList if c <= change]: # 常用
num = 1 + recMD(valueList, change - i, Knowlist)
if num < minNum:
minNum = num
Knowlist[change] = minNum
return minNum # 最后记得要返回
print(time.process_time()) # time.clock()被抛弃
print(recMD([1, 5, 10, 25], 77, [0]*79)) # 创建全为0的表
print(time.process_time())
递归 + 记忆 + 输出过程:
import time
from pythonds.basic.stack import Stack
def dp(valueList, change, minNum, coinUsed): # minNum初始化为0,之后需要利用到这些数据
for cents in range(1, change+1): # 从小到大递推
coinCount = cents # 初始化一个无害的最小值
newCoin = 1
for j in [c for c in valueList if c <= cents]: # 常用技巧
if 1 + minNum[cents-j] < coinCount:
coinCount = 1 + minNum[cents - j]
newCoin = j
minNum[cents] = coinCount
coinUsed[cents] = newCoin # 每一个change的最优解都是由两部分组成,这里是记录其中一部分
return minNum[change]
def printSelection(change, coinused):
coin = change
s = Stack()
while coin > 0:
thisCoin = coinused[coin]
s.push(thisCoin)
coin = coin - thisCoin
while not s.isEmpty():
print(s.pop())
valList = [1, 5, 10, 25]
amnt = 63
minN = [0]*64
coinUsed = [0]*64
print(dp(valList, amnt, minN, coinUsed)) # 创建表的方式get
print(coinUsed[1:]) # 打印全部
printSelection(amnt, coinUsed) # 打印组成部分
备注:
动态规划解法的必要条件:问题的最有解包含了更小规模的最优解,即每一步都要依靠前面某步的最优解
Talk is cheap. Show me the code. 将算法思路转化成具体代码需要不断实践,积累经验