{x}
blog image

Coin Change

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

Solution Explanation: Coin Change

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.

Approach: Dynamic Programming

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.

  1. Initialization:

    • dp[0] = 0 (0 coins needed to make amount 0).
    • Initialize the rest of the dp array to a large value (infinity) to represent that we haven't yet found a solution for those amounts.
  2. Iteration: Iterate through each coin denomination (coin) in the coins array and for each amount i from coin up to the target amount:

    • If 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)
  3. 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.

Time and Space Complexity

  • Time Complexity: O(amount * number of coins). We iterate through the dp array once for each coin.
  • Space Complexity: O(amount). We use a dp array of size amount + 1.

Code Implementation (Python)

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
 

Code Implementation (Other Languages)

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.