Solution 1

  • TimeO(n * m)
  • SpaceO(n)

Where, n is the amount, m is number of coins.
This is a Top-Down approach, a recursive solution with memoization.
This is more intuitive to think of than Bottom-Up approach.

Python
class Solution:
    '''
    Time Complexity: O(n * m)
    Space Complexity: O(n)
    Where, n is the amount, m is number of coins.
    This is a Top-Down approach, a recursive solution with memoization.
    This is more intuitive to think of than Bottom-Up approach.
    '''
    def coinChange(self, coins: List[int], amount: int) -> int:
        cache = {0: 0}

        def dfs(target):
            if target in cache:
                return cache[target]
            if target < 0:
                return -1

            res = float('inf') # Can use `amount + 1` instead of `float('inf')` because max coins needed will be amount (all 1s) if "1" coin exists
            for coin in coins:
                tres = dfs(target-coin)
                if tres > -1:
                    res = min(res, tres+1)

            if res == float('inf'): # Can use `amount + 1` instead of `float('inf')`
                cache[target] = -1
                return -1 
            
            cache[target] = res
            return res

        return dfs(amount)
Leet Code/python.py · L2950–2981

Solution 2

  • TimeO(n * m)
  • SpaceO(n)

Where, n is the amount, m is number of coins.
This is a Bottom-Up approach, an iterative solution with Dynamic Programming.

Python
class Solution:
    '''
    Time Complexity: O(n * m)
    Space Complexity: O(n)
    Where, n is the amount, m is number of coins.
    This is a Bottom-Up approach, an iterative solution with Dynamic Programming.
    '''
    def coinChange(self, coins: List[int], amount: int) -> int:
        dp = [amount + 1] * (amount + 1)
        dp[0] = 0
        for a in range(1, amount + 1):
            for c in coins:
                if a - c >= 0:
                    dp[a] = min(dp[a], 1 + dp[a - c])
        return dp[amount] if dp[amount] != amount + 1 else -1
Leet Code/python.py · L2983–2998