You are given an integer array coins
representing coins of different denominations and an integer amount
representing a total amount of money. Your task is to write a function that returns 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
Clarifications:
coins
array is empty?Write a function to solve the coin change problem efficiently, considering potential edge cases and optimizing for time and space complexity. Explain the time and space complexity of your solution.
You are given an integer array coins
representing coins of different denominations and an integer amount
representing a total amount of money. The goal is to find 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
. Assume that you have an infinite number of each kind of coin.
A simple, but inefficient, approach is to try every possible combination of coins recursively. For each coin, we either include it or exclude it, and explore all resulting possibilities.
Code (Python):
def coin_change_recursive(coins, amount):
if amount == 0:
return 0
if amount < 0:
return -1
min_coins = float('inf')
for coin in coins:
res = coin_change_recursive(coins, amount - coin)
if res != -1:
min_coins = min(min_coins, res + 1)
return min_coins if min_coins != float('inf') else -1
Explanation:
Time Complexity: O(branches^depth), where branches is the number of coin denominations and depth is the amount. This leads to exponential time complexity. Specifically, O(n^amount), where n is the number of coins.
Space Complexity: O(amount) due to the call stack depth of the recursion.
A much more efficient solution can be obtained using dynamic programming. We build a table dp
where dp[i]
stores the minimum number of coins needed to make up amount i
. We iterate from 1 to amount
, and for each amount i
, we iterate through the coins. If a coin's value is less than or equal to i
, we check if using that coin gives us a better result than the current minimum for dp[i]
.
Code (Python):
def coin_change_dp(coins, amount):
dp = [float('inf')] * (amount + 1)
dp[0] = 0
for i in range(1, amount + 1):
for coin in coins:
if coin <= i:
dp[i] = min(dp[i], dp[i - coin] + 1)
return dp[amount] if dp[amount] != float('inf') else -1
Explanation:
dp
array with infinity, except dp[0] = 0
(0 coins needed to make amount 0).amount
.i
, iterate through the coins. If a coin's value is less than or equal to i
, update dp[i]
with the minimum of its current value and dp[i - coin] + 1
.dp[amount]
if it's not infinity, otherwise return -1.Time Complexity: O(amount * n), where amount
is the target amount and n
is the number of coin denominations.
Space Complexity: O(amount), for the dp
array.
coins
array: If the coins
array is empty, and the amount is not zero, it's impossible to make the amount. Return -1.amount
is 0: If the amount
is 0, no coins are needed. Return 0.dp[amount]
remaining as infinity. Return -1.coins
array doesn't change the solution.