【LeetCode】322, change exchange

322. Change Exchange

1. Violent recursion

coinChange([1,2,5], 11) = 1 + min( coinChange([1,2,5], 10), coinChange([1,2,5], 9, coinChange([1,2,5 ], 6) )

import sys


class Solution:
    def coinChange(self, coins: [], amount: int) -> int:
        if amount == 0:
            return 0
        if amount < 0:
            return -1
        res = sys.maxsize
        for coin in coins:
        	# 计算子问题的结果
            subProblem = self.coinChange(coins, amount - coin)
            # 子问题无解则跳过
            if subProblem == -1:
                continue
            # 在子问题中选最优解,然后+1
            res = min(res, subProblem + 1)
        if res == sys.maxsize:
            return -1
        else:
            return res


if __name__ == '__main__':
    coins = [1, 2, 5]
    amount = 11
    x = Solution().coinChange(coins, amount)
    print(x)

insert image description here

2. Recursion with memo

However, the above violent recursion has repeated calculation, such as coinChange(coins, 9) corresponding to the yellow square in the above figure is repeated.

import sys


class Solution:
    def coinChange(self, coins: [], amount: int) -> int:
        memo = [-666 for i in range(0, amount+1)]  # 赋初值,用于区分未计算的,还是计算过但值为0的
        return self.helper(coins, amount, memo)

    def helper(self, coins: [], amount: int, memo: []) -> int:
        if amount == 0:
            return 0
        if amount < 0:
            return -1
        if memo[amount] != -666:
            return memo[amount]
        res = sys.maxsize
        for coin in coins:
            # 计算子问题的结果
            subProblem = self.helper(coins, amount - coin, memo)
            # 子问题无解则跳过
            if subProblem == -1:
                continue
            # 在子问题中选最优解,然后+1
            res = min(res, subProblem + 1)
        memo[amount] = res
        if res == sys.maxsize:
            return -1
        else:
            return res


if __name__ == '__main__':
    coins = [1, 2, 5]
    amount = 11
    x = Solution().coinChange(coins, amount)
    print(x)

Since the time complexity of recursion is equal to the number of recursion (N times) times the complexity inside the recursive function (O(k)), the time complexity is O(k * N).

3. Dynamic programming

The iterative process from bottom to top is as follows:

insert image description here

class Solution:
    def coinChange(self, coins: [], amount: int) -> int:
        dp = [amount + 1 for i in range(0, amount+1)]
        dp[0] = 0
        for a in range(0, amount+1):
            for coin in coins:
                if coin > a:
                    continue
                dp[a] = min(dp[a], dp[a-coin]+1)
        if dp[amount] == amount + 1:
            return -1
        return dp[amount]


if __name__ == '__main__':
    coins = [2]
    amount = 3
    x = Solution().coinChange(coins, amount)
    print(x)

Guess you like

Origin blog.csdn.net/jiaoyangwm/article/details/127479324