Given coins of different denominations
coins
and a total amountamount
. Write a function to calculate the coins that can make up the total amount组合数
. Suppose there are infinite coins of each denomination.
This question is 0-1
a variant of the knapsack problem, which is a complete knapsack problem, so what is a complete knapsack problem?
Let's review the problem of 0-1 backpack again : give you a W
backpack and N
items (each item is different) that can be loaded with a weight of 1 , and each item has two attributes: weight and value. i
The weight of the first item is wt[i]
and the value is val[i]
. Now let you use this backpack to pack the item, what is the maximum value that can be loaded?
0-1
The number of items in the backpack problem is limited. To be precise, each item is unique, and there are infinite coins of each denomination here. That is 完全背包问题
, the idea is the same as the idea of a 0-1 backpack, but The state transition equation is slightly changed.
We can 0-1
solve this problem according to the idea of backpack :
We compare coins of different denominations to 0-1
items in the knapsack problem, and compare the total amount to the capacity of the knapsack, so that it can be transformed into a knapsack problem model for solution.
- The first step: clarify "status" and "choice"
There are two states, namely "the capacity of the backpack" and "optional items", the choice is "pack in the backpack" or "not in the backpack".
for 状态1 in 状态1的所有取值:
for 状态2 in 状态2的所有取值:
for ...
dp[状态1][状态2][...] = 计算(选择1,选择2...)
- Clear definition of array
dp
dp[i][j]
Is defined as follows: only the first i
two items, when the capacity of the backpack j
when there are dp[i][j]
ways to fill the backpack.
Converted to a coin changer model is to: use only coins
the front i
coins face value, if you want Couchu amount j
, there are dp[i][j]
kinds of error method.
The base case is dp[0][..] = 0, dp[..][0] = 1
. Because if you don't use any coin face value, you can't make up any amount; if the target amount is 0, then "rule by doing nothing" is the only way to make up.
Our ultimate goal is to find dp[N][amount]
, which N
is the coins
size of the array.
- According to "choice", think about the logic of state transition
If you do not use coins[i]
the face value of the coin, so Couchu denomination j
several methods dp[i][j]
should be equal dp[i-1][j]
, inherited the previous results.
If you use coins[i]
the face value of the coin, it dp[i][j]
should be equal dp[i][j-coins[i-1]]
.
First, as i
it is from the beginning, so coins
the index is i-1
time represents the i
face value of the coins.
dp[i][j-coins[i-1]]
It is not difficult to understand that if you decide to use this coin, then you should pay attention to how to collect the amount j - coins[i-1]
.
In sum it is two options, and we want to ask of dp[i][j]
a "total number of species and error", so dp[i][j]
the value should be more than the sum of the results of the two options:
class Solution {
int change(int amount, int[] coins) {
int n = coins.length;
int[][] dp = amount int[n + 1][amount + 1];
for (int i = 0; i <= n; i++) {
dp[i][0] = 1;
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= amount; j++){
if (j - coins[i-1] >= 0){
dp[i][j] = dp[i - 1][j] + dp[i][j - coins[i-1]];
}else {
dp[i][j] = dp[i - 1][j];
}
}
}
return dp[n][amount];
}
}
Moreover, we can discover through observation, dp
transfer the array and only dp[i][..]
and dp[i-1][..]
relevant:
Therefore, the state can be compressed to further reduce the space complexity of the algorithm:
class Solution {
public int change(int amount, int[] coins) {
int n = coins.length;
int[] dp = new int[amount + 1];
dp[0] = 1;
for (int i = 0; i < n; i++){
for (int j = 1; j <= amount; j++){
if (j - coins[i] >= 0){
dp[j] += dp[j-coins[i]];
}
}
}
return dp[amount];
}
}
It can even do this:
class Solution {
public int change(int amount, int[] coins) {
int[] dp = new int[amount + 1];
dp[0] = 1;
for (int coin : coins) {
// j直接从coin开始,避免了j - coins[i] >= 0的判断
for (int j = coin; j <= amount; j++) {
dp[j] += dp[j - coin];
}
}
return dp[amount];
}
}
Time complexity O(N*amount)
Space complexity O(amount)