[LeetCode] 由 「找零錢" 所想

 

Ref[Optimization] Dynamic programming【尋找子問題】html

 

Ref[Optimization] Advanced Dynamic programming【優於recursion】緩存

 

 

 

顯然,本篇是關於」動態規劃"的部分。ui


找零錢 

1、簡單直白策略

要點:」個數「其實表明了「for循環」的層數。但「個數」不定,使用「遞歸」反而能解決這個問題,減小思路上的負擔。 this

import time 

def recMC(coinValueList, change):
minCoins
= change if change in coinValueList: return 1 else: for i in [c for c in coinValueList if c <= change]: # 遍歷每個變量, 至關於多重循環。有意思的是,循環的深度是不肯定的; numCoins = 1 + recMC(coinValueList, change-i)
# 獲得這個遍歷分支的最終結果; if numCoins < minCoins: minCoins = numCoins
return minCoins start = time.time() print(recMC([1,5,10,25], 63)) end = time.time() print(end-start)

耗時:31秒。spa

 

 

2、記憶化策略

要點:增長了」結果緩存「,效率極具增長。3d

 

代碼中的 knownResults 記錄了上圖中節點(某個change時)的最優/最小的值,做爲了記錄。code

def recDC(coinValueList, change, knownResults):
minCoins
= change if change in coinValueList: knownResults[change] = 1  # 一個硬幣剛恰好 return 1 elif knownResults[change] > 0: return knownResults[change] else: for i in [c for c in coinValueList if c <= change]:
# numCoins
= 1 + recDC(coinValueList, change-i, knownResults)
# 更新minCoins if numCoins < minCoins: minCoins = numCoins knownResults[change] = minCoins return minCoins
def main():
amnt = 2163
print(recDC([1,2,5,10,21,25], amnt, [0]*(amnt+1))) main()

耗時:0.01秒。htm

 

 

3、動態規劃策略

  要點:不是從上到下的 (遞歸) 思惟,且容易棧溢出;而是從最小的狀況入手,逐漸擴大。blog

def dpMakeChange(coinValueList, change, minCoins, coinsUsed):
    # 首先,考慮全部的 "狀況",是從小到大考慮
    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: 
                coinCount = minCoins[cents-j] + 1
                newCoin = j
        
        # 考慮過該 "狀況",更新記錄
        minCoins[cents]  = coinCount
        coinsUsed[cents] = newCoin
    
    return minCoins[change]


def printCoins(coinsUsed, change):
    coin = change
    while coin > 0:
        thisCoin = coinsUsed[coin]
        print(thisCoin)
        coin = coin - thisCoin

@fn_timer
def main():
    amnt = 2163
    clist = [1,2,5,10,21,25]
    coinsUsed = [0]*(amnt+1)
    coinsCount = [0]*(amnt+1)

    # print("Making change for", amnt, "requires")
    print(dpMakeChange(clist, amnt, coinsCount, coinsUsed), "coins")
    # print("They are:")
    # printCoins(coinsUsed,amnt)
    # print("The used list is as follows:")
    # print(coinsUsed)

main()

耗時:0.003秒。遞歸

 

End.

相關文章
相關標籤/搜索