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
The problem asks for the minimum number of coins needed to make up a given amount, given an array of coin denominations. This is a classic dynamic programming problem.
We can solve this using dynamic programming by building a table (or array) where dp[i]
represents the minimum number of coins needed to make up the amount i
.
Initialization:
dp[0] = 0
(0 coins needed to make amount 0).dp
array to a large value (infinity) to represent that we haven't yet found a solution for those amounts.Iteration: Iterate through each coin denomination (coin
) in the coins
array and for each amount i
from coin
up to the target amount
:
dp[i - coin]
is not infinity (meaning we have a solution for i - coin
), then we can potentially improve the solution for i
by using one coin
in addition to the solution for i - coin
:
dp[i] = min(dp[i], dp[i - coin] + 1)
Result: After iterating through all coins and amounts, dp[amount]
will contain the minimum number of coins needed to make up the target amount. If dp[amount]
remains infinity, it means no solution exists.
dp
array once for each coin.dp
array of size amount + 1
.This solution uses a 1D dp
array for space optimization:
def coinChange(coins, amount):
dp = [float('inf')] * (amount + 1) # Initialize dp array with infinity
dp[0] = 0 # Base case: 0 coins needed for amount 0
for coin in coins:
for i in range(coin, amount + 1):
if dp[i - coin] != float('inf'):
dp[i] = min(dp[i], dp[i - coin] + 1)
return dp[amount] if dp[amount] != float('inf') else -1 #Return -1 if no solution found
The logic remains the same across different programming languages. Here are examples in Java and C++:
Java:
class Solution {
public int coinChange(int[] coins, int amount) {
int[] dp = new int[amount + 1];
Arrays.fill(dp, amount + 1); // Initialize with a large value
dp[0] = 0;
for (int coin : coins) {
for (int i = coin; i <= amount; i++) {
dp[i] = Math.min(dp[i], dp[i - coin] + 1);
}
}
return dp[amount] > amount ? -1 : dp[amount];
}
}
C++:
class Solution {
public:
int coinChange(vector<int>& coins, int amount) {
vector<int> dp(amount + 1, amount + 1); // Initialize with a large value
dp[0] = 0;
for (int coin : coins) {
for (int i = coin; i <= amount; i++) {
dp[i] = min(dp[i], dp[i - coin] + 1);
}
}
return dp[amount] > amount ? -1 : dp[amount];
}
};
These implementations follow the same dynamic programming approach, efficiently finding the minimum number of coins or returning -1 if no solution exists. The choice of language only affects the syntax and specific library functions used (like Arrays.fill
in Java or vector
and min
in C++). The core algorithm is identical.