Sulba
000 / 100

Coin Change

MediumTime O(amount × number of coins)Space O(amount)LeetCode 322 ↗

The problem

Given coin values coins (as many of each as you like) and an amount, return the fewest coins that add up to exactly amount, or −1 if it cannot be made.

Examples

01
Input
coins = [1, 2, 5], amount = 11
Output
3
02
Input
coins = [2], amount = 3
Output
-1
03
Input
coins = [1], amount = 0
Output
0

Constraints

  • 1 ≤ coins.length ≤ 12
  • 1 ≤ coins[i] ≤ 2³¹ − 1
  • 0 ≤ amount ≤ 10⁴

The idea

Taking the biggest coin first can fail: with coins 1, 3, 4 and amount 6, greedy gives 4 + 1 + 1 (three coins) but 3 + 3 is two.

Instead, let fewest[x] be the fewest coins making x. The last coin used is some c, and what is left, x − c, must itself be made as cheaply as possible: fewest[x] = 1 + the smallest fewest[x − c] over coins c ≤ x. Fill it from 0 (which needs none) up to amount; an amount no coin combination makes stays at “infinity” — here, amount + 1, more coins than could ever be needed.

Time
O(amount × number of coins)
Space
O(amount)

Solution · every language run against every case

class Solution:    def coinChange(self, coins: List[int], amount: int) -> int:        # fewest[x]: the fewest coins making x. The last coin is some c, so        # fewest[x] = 1 + min(fewest[x - c]) over every coin c <= x.        INF = amount + 1  # more coins than could ever be needed        fewest = [0] + [INF] * amount        for x in range(1, amount + 1):            for c in coins:                if c <= x and fewest[x - c] + 1 < fewest[x]:                    fewest[x] = fewest[x - c] + 1        return -1 if fewest[amount] == INF else fewest[amount]