Problem: Coin Change (Minimum Coins)
You are given a list of coins with different denominations and a target amount. The goal is to determine the fewest number of coins needed to make up that amount. If it’s impossible to make up that amount, return -1.
Dynamic Programming Approach Explanation:
This is a classic problem that can be solved using Dynamic Programming (DP). We will use a bottom-up approach where we build the solution incrementally, starting from the smallest subproblems (amount 0) and gradually increasing to the target amount.
Concept:
-
State Representation:
Letdp[i]represent the fewest number of coins required to make amounti. -
Initialization:
- Set
dp[0] = 0, because zero amount requires zero coins. - For other amounts
i > 0, initializedp[i] = infinity(or a large value) because initially, we assume it’s impossible to form that amount.
- Set
-
State Transition:
For each coin denomination, update thedparray. If we can make the amounti - coin, then we can make the amountiby adding one more coin. Therefore:dp[i]=min(dp[i],dp[i−coin]+1)dp[i] = min(dp[i], dp[i – coin] + 1)
-
Final Answer:
After processing all coins,dp[amount]will give the minimum number of coins required for the target amount. Ifdp[amount]is still infinity, it means the target amount cannot be formed with the given coins, and we return-1.
Example:
Input:coins = [1, 2, 5], amount = 11
Step-by-step DP Table:
| Amount | dp[Amount] | Explanation |
|---|---|---|
| 0 | 0 | No coins needed for amount 0 |
| 1 | 1 | Use one coin of 1 |
| 2 | 1 | Use one coin of 2 |
| 3 | 2 | Use one coin of 2 + one coin of 1 |
| 4 | 2 | Use two coins of 2 |
| 5 | 1 | Use one coin of 5 |
| 6 | 2 | Use one coin of 5 + one coin of 1 |
| 7 | 2 | Use one coin of 5 + two coins of 1 |
| 8 | 3 | Use one coin of 5 + one coin of 2 |
| 9 | 3 | Use one coin of 5 + two coins of 2 |
| 10 | 2 | Use two coins of 5 |
| 11 | 3 | Use one coin of 5 + one coin of 5 + one coin of 1 |
Answer: 3, because we need 3 coins: 5 + 5 + 1.
C Code:
#include <stdio.h>
#include <limits.h>
int coinChange(int* coins, int coinsSize, int amount) {
int dp[amount + 1];
// Initialize the dp array with a large value
for (int i = 0; i <= amount; i++) {
dp[i] = INT_MAX;
}
dp[0] = 0; // No coins needed to make amount 0
// Bottom-up DP
for (int i = 1; i <= amount; i++) {
for (int j = 0; j < coinsSize; j++) {
if (i >= coins[j] && dp[i - coins[j]] != INT_MAX) {
dp[i] = dp[i] < dp[i - coins[j]] + 1 ? dp[i] : dp[i - coins[j]] + 1;
}
}
}
// If dp[amount] is still INT_MAX, it means we cannot form the amount
return dp[amount] == INT_MAX ? -1 : dp[amount];
}
int main() {
int coins[] = {1, 2, 5};
int coinsSize = 3;
int amount = 11;
int result = coinChange(coins, coinsSize, amount);
printf("Minimum number of coins: %dn", result);
return 0;
}
Python Code:
def coinChange(coins, amount):
# Initialize dp array with infinity, except dp[0] which is 0
dp = [float('inf')] * (amount + 1)
dp[0] = 0
# Bottom-up DP
for i in range(1, amount + 1):
for coin in coins:
if i >= coin:
dp[i] = min(dp[i], dp[i - coin] + 1)
# If dp[amount] is still infinity, return -1, otherwise return dp[amount]
return dp[amount] if dp[amount] != float('inf') else -1
# Example Usage:
coins = [1, 2, 5]
amount = 11
result = coinChange(coins, amount)
print(f"Minimum number of coins: {result}")
Explanation of Code:
-
Initialization:
- In both C and Python, the
dparray is initialized to represent the fewest coins needed for every amount from0toamount. Initially, all amounts are set to a large value (INT_MAXin C andfloat('inf')in Python) exceptdp[0], which is set to 0 (because no coins are needed to make amount 0).
- In both C and Python, the
-
Filling the DP Table:
- For each amount from
1toamount, iterate through each coin. If we can use that coin (i.e.,i >= coin), then update thedp[i]value by considering using that coin: dp[i]=min(dp[i],dp[i−coin]+1)dp[i] = min(dp[i], dp[i – coin] + 1) - This ensures we get the minimum number of coins for each amount.
- For each amount from
-
Final Check:
- After filling the DP table, if
dp[amount]is still infinity (INT_MAXorfloat('inf')), it means it’s not possible to make that amount with the given coins, so return-1. Otherwise, returndp[amount], which is the minimum number of coins needed.
- After filling the DP table, if
Time and Space Complexity:
-
Time Complexity:
- The time complexity is O(amount * coins), where
amountis the target amount andcoinsis the number of coin denominations. For each amount, we check every coin denomination.
- The time complexity is O(amount * coins), where
-
Space Complexity:
- The space complexity is O(amount) because we only need a
dparray of sizeamount + 1.
- The space complexity is O(amount) because we only need a
Example Output:
-
Input:
coins = [1, 2, 5],amount = 11Output:
3(because 11 = 5 + 5 + 1) -
Input:
coins = [2],amount = 3Output:
-1(because it’s impossible to make amount 3 with only coin 2) -
Input:
coins = [1],amount = 0Output:
0(no coins needed to make amount 0)
This dynamic programming approach is efficient and works well within the given problem constraints.
