Coin change

Problem Overview
The Coin Change problem is a classic dynamic programming question frequently encountered in algorithm interviews. The problem statement can be described as follows:
You are given coins of different denominations and a total amount of money. Write an algorithm to compute the fewest number of coins that you need to make up that amount. If it is impossible to make up the amount with the given denominations, return -1.
Example:
Input: coins = [1, 2, 5], amount = 11
Output: 3
Explanation: 11 = 5 + 5 + 1
Constraints:
- 1 ≤ coins.length ≤ 12
- 1 ≤ coins[i] ≤ 2^31 - 1
- 0 ≤ amount ≤ 10^4
Understanding the Problem
The goal is to determine the minimum number of coins needed to make up a specified amount using the given denominations. The solution must consider all possible combinations of coins, ensuring that the minimum combination is found. One crucial observation is that we can use the technique of recursion with memoization or dynamic programming to find an efficient solution, as the problem exhibits the optimal substructure and overlapping subproblems.
Key DSA Concepts and Theory
Dynamic Programming
Dynamic Programming (DP) is a method for solving complex problems by breaking them down into simpler subproblems. It is applicable when the problem has overlapping subproblems or exhibits the property of optimal substructure. The key to solving problems via DP is to store the solutions of subproblems to avoid redundant computations.
Problem Representation
- State Definition: Define
dp[i]
as the fewest number of coins required to make the amounti
. - Base Case:
dp[0] = 0
, because no coins are needed to make the amount zero. - Recurrence Relation: For every coin
c
incoins
and for every amountj
, ifj >= c
, thendp[j] = min(dp[j], 1 + dp[j - c])
.
Solution Approach
Step-by-Step Solution
Step 1: Initialize the DP Table
- Create an array
dp
of sizeamount + 1
initialized to a large number (sayamount + 1
) to indicate that initially, all sums are unreachable. - Set
dp[0] = 0
to represent the base case.
Step 2: Build the Solution Bottom-Up
- Iterate over all possible coin values.
- For each coin, iterate through potential amounts from the coin's value up to the desired amount.
- Update the
dp
array using the recurrence relation.
Step 3: Return the Result
- If
dp[amount]
is still a large number, return-1
indicating the amount cannot be formed. Otherwise, returndp[amount]
.
Code Examples
C++ Solution
#include <vector>
#include <algorithm>
class Solution {
public:
int coinChange(std::vector<int>& coins, int amount) {
std::vector<int> dp(amount + 1, amount + 1);
dp[0] = 0;
for (int i = 1; i <= amount; ++i) {
for (const int& coin : coins) {
if (i - coin >= 0) {
dp[i] = std::min(dp[i], dp[i - coin] + 1);
}
}
}
return dp[amount] > amount ? -1 : dp[amount];
}
};
Java Solution
import java.util.Arrays;
class Solution {
public int coinChange(int[] coins, int amount) {
int[] dp = new int[amount + 1];
Arrays.fill(dp, amount + 1);
dp[0] = 0;
for (int i = 1; i <= amount; i++) {
for (int coin : coins) {
if (i - coin >= 0) {
dp[i] = Math.min(dp[i], dp[i - coin] + 1);
}
}
}
return dp[amount] > amount ? -1 : dp[amount];
}
}
Time and Space Complexity Analysis
- Time Complexity:
O(n * amount)
wheren
is the number of coin denominations. Each coin tries to fill each amount up to the target once. - Space Complexity:
O(amount)
, where we store at most one solution for each amount leading up to the target.
Common Mistakes to Avoid
- Not handling the base case properly (
dp[0] = 0
). - Failing to initialize the
dp
array with values greater thanamount
to signify that these amounts are initially unreachable. - Confusing the state transition and incorrect indexing can lead to wrong answers or runtime errors.
Similar Problems on LeetCode
- 518. Coin Change 2
- 322. Coin Change (Similar to this problem, but differently worded)
Additional Resources and References
This article should provide a thorough understanding of the Coin Change problem, including problem comprehension, solution strategy using dynamic programming, and coding implementation in both C++ and Java.