Problem
Source: Leetcode
You are given coins of different denominations and a total amount of money amount. Write a function to compute 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.
Examples:
Input: coins = {1,2,5}, amount = 11
Output: 3 //2 đồng 5 và 1 đồng 1
Input: coins = {2}, amount = 3
Output: -1
Solution
Approach 1: Brute force
By above example, amount = 11. Let’s image 5 is the last used coin then the fewest coins we need will be the fewest coins to make change whatever is left plus 1. In other words, $$coinChange(11) = coinChange(11 - 5) + 1$$ Meanwhile, the problem become fewest coins make change whatever is left. This is a subproblem. Same as coin 1 and 2, those subproblem can be showed as a diagram like this:
Approach 2: Dynamic programing
By the idea above, this time i have an array like this, called dp
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
---|---|---|---|---|---|---|---|---|---|---|---|
Each cell is a subproblem: Fewest coins make change the amount $i$. So, the answer at $11^th$ cell is the answer that we’re looking for this problem. And because it’s calculated by the cells on its left, so we can reused the answer of the subprolem and avoid duplicating them.
To begin, i’ll fill the array like this:
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | 12 | 12 | 12 | 12 | 12 | 12 | 12 | 12 | 12 | 12 | 12 |
For each cell, i’ll consider each coin whether it is greater than the amount at that cell. If not, which means we can use that coin, the value for that cell would be $$dp[i] = min(dp[i-coin] + 1,dp[i])$$ If $i = 1$ then $dp[1] = min(0+1, 12)$. Just like that, at the end, the array will be filled as:
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 1 | 2 | 2 | 1 | 2 | 2 | 3 | 3 | 2 | 3 |
$11^th$ cell’s value is 3, that is the answer for the example test. From there, i have a code like this:
vector<int> dp(amount+1, amount+1);
dp[0] = 0;
for(int i = 1; i <= amount; i++)
for(int coin : coins)
if(coin <= i && dp[i - coin] + 1 < dp[i])
dp[i] = dp[i - coin] + 1;
return dp[amount];
That’s is the idea. But in reality, this code would recieve wrong answer
instantly after submit, because of the careless when we read the problem. They said:
If that amount of money cannot be made up by any combination of the coins, return
-1
. So we need to editreturn
line for that case to getpassed
UwU.
return (dp[amount] <= amount ? dp[amount] : -1);
Thank you for reading.