Python版-LeetCode 學習:零錢兌換問題

給定不同面額的硬幣 coins 和一個總金額 amount。編寫一個函數來計算可以湊成總金額所需的最少的硬幣個數。如果沒有任何一種硬幣組合能組成總金額,返回 -1。

說明:你可以認爲每種硬幣的數量是無限的。
鏈接:https://leetcode-cn.com/problems/coin-change

多種方法的思考:

方法1:遞歸

class Solution:
    def coinChange(self, coins: List[int], amount: int) -> int:
        
        def count(n):
            # 基本情況的判定
            if n==0 : return 0
            if n<1 : return -1
            # 初始化
            min_coins=float('INF')
            for coin in coins:
                # 子問題的分解
                subproblem=count(n-coin)
                if subproblem == -1:
                    continue
                # 
                min_coins=min(min_coins,1+subproblem)
            # 如果一直continue,min_coins 不變,就代表沒有可以分的可能
            return min_coins if min_coins !=float('INF') else -1

        return count(amount)

方法二: 加入記錄表的迭代

class Solution:
    def coinChange(self, coins: List[int], amount: int) -> int:
        
        memo={}
        def count(n):
            # 查找子問題的值
            if n in memo:
                return memo[n]
            if n==0 : return 0
            if n<1 : return -1
            # 初始化
            min_coins=float('INF')
            for coin in coins:
                # 子問題分解
                subproblem=count(n-coin)
                if subproblem == -1:
                    continue
                min_coins=min(min_coins,1+subproblem)
            # 存儲子問題的解
            memo[n]= min_coins if min_coins !=float('INF') else -1
            return memo[n]

        return count(amount)

方法三:用list代替dict中間表的迭代

class Solution:
    def coinChange(self, coins: List[int], amount: int) -> int:
        # 初始化結果集
        # 每一個下標對應對應amount,下標對應的最後元素值就是零錢的最小個數
        res=[float('INF')]*(amount+1)
        
        res[0]=0
        for i in range(amount+1):

            for coin in coins:
                # 不可分就下一輪
                if (i-coin) <0: continue
                # 對每一個i進行計算
                res[i]=min(res[i],1+res[i-coin])

        if res[amount] == float('INF'):
            return -1
        else:
            return res[amount]

方法四:利用整除減少循環次數

class Solution:
    def coinChange(self, coins: List[int], amount: int) -> int:
        
        n = len(coins)
        coins.sort(reverse=True)
        self.res = float("inf")
        def dfs(index,target,count):
            coin = coins[index]
            if math.ceil(target/coin)+count>=self.res:
                return
            if target%coin==0:
                self.res = count+target//coin
            if index==n-1:return
            print([range(target//coin,-1,-1)])
            for j in range(target//coin,-1,-1):
                dfs(index+1,target-j*coin,count+j)
        dfs(0,amount,0)

        return int(self.res) if self.res!=float("inf") else -1

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章