LC518 - Coin Change II
Problem
You are given an integer array coins
representing coins of different denominations and an integer amount
representing a total amount of money.
Return the number of combinations that make up that amount. If that amount of money cannot be made up by any combination of the coins, return 0
.
You may assume that you have an infinite number of each kind of coin.
The answer is guaranteed to fit into a signed 32-bit integer.
Example
Input: amount = 5, coins = [1,2,5]
Output: 4
Explanation: there are four ways to make up the amount:
5=5
5=2+2+1
5=2+1+1+1
5=1+1+1+1+1
Solution
DFS
The naive approach uses a DFS to go through the entire decision tree to evaluate possible paths of coin selections. To prevent duplicates, i.e. 2+2+1 and 2+1+2, paths will only evaluate coins with greater or equal value to the first selection (first node). The time complexity of this approach is , where is the number of coins and is the total amount.
Cached DFS
Caching (in theory) reduces the time complexity to , as repeated evaluations are returned from cache. The cache uses space. However, it seems that it does not perform optimally in this implementation upon evaluation.
def change(self, amount: int, coins: List[int]) -> int:
@cache
def dfs(i, target):
if target == amount:
return 1
if target > amount or i == len(coins):
return 0
return dfs(i, target + coins[i]) + dfs(i+1, target)
return dfs(0,0)
2D Dynamic Programming
The advantage of using DP is that the space complexity goes down to . For
def change(self, amount: int, coins: List[int]) -> int:
arr = [0] * (amount + 1)
arr[0] = 1
for i in range(len(coins), 0, -1):
next = [0] * (amount+1)
next[0] = 1
for target in range(1, amount+1):
next[target] = arr[target]
if target - coins[i-1] >= 0:
next[target] += next[target-coins[i-1]]
arr = next
return arr[amount]
Last updated