Coin Change

You are given an integer arrayĀ coinsĀ representing coins of different denominations and an integerĀ amountĀ representing a total amount of money.

ReturnĀ the fewest number of coins that you need to make up that amount. If that amount of money cannot be made up by any combination of the coins, returnĀ -1.

You may assume that you have an infinite number of each kind of coin.

Example 1:

Input: coins = [1,2,5], amount = 11
Output: 3
Explanation: 11 = 5 + 5 + 1

Example 2:

Input: coins = [2], amount = 3
Output: -1

Example 3:

Input: coins = [1], amount = 0
Output: 0

Constraints:

  • 1 <= coins.length <= 12
  • 1 <= coins[i] <= 231 - 1
  • 0 <= amount <= 104
    `

Intuition

We need to try out all the coins. Let's get an example of amount 7 with value [1,3,5]

We have:

  • If the amount is 1:
    • We can use 1 coin 1
  • If the amount is 2:
    • We can use 2 coin 1
  • If the amount is 3:
    • We can use 3 coin 1 or 1 coin 3
  • If the amount is 4:
    • We can use 4 coin 1 or 1 coin 3 and 1 coin 1
  • If the amount is 5:
    • We can use 5 coin 1, 1 coin 3 and 2 coin 1, or 1 coin 5

The pattern is given coin[i], we have the following formula:

result_at_amount = 1 + result(amount - coin[i])

Explain:

  • Given an amount (for example 5), and a list of coins (1, 3, 5)
  • Say if we pick a random coin to use (3), the number of way that we can form 5 is
    • result = min_coin(5 - 3) + 1
    • +1 is because we are using the current coin so it add as the number of coins.
    • min_coin(5-3) = min_coin(2) since we used 3 already we have to find the minimum coin to make 2.

Implementation

class App:
    def coinChange(self, coins: List[int], amount: int) -> int:
        dp = [float('inf') for _ in range(amount + 1)]
        
        dp[0] = 0

        for i in range(1, len(dp)):
            for coin in coins:
                if coin > i: continue
                if coin == i: 
                    dp[i] = 1
                    break

                dp[i] = min(dp[i], dp[i - coin] + 1)

        return dp[amount] if dp[amount] != float('inf') else -1

Time complexity: $O(amount \times coin)$
Space complexity: $O(n)$