322. Change exchange - LeetCode
You are given an array of integers coins
representing coins of different denominations and an integer amount
representing the total amount. Calculate and return the minimum number of coins required to make up the total amount . If no coin combination completes the total amount, return it . -1
You can think of the number of each type of coin as infinite .
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
>>Ideas and analysis
- The question says that the number of each type of coins is infinite, which can be seen as a typical complete knapsack problem~
- And this question asks for the minimum number of coins, then the coins can be in order or not, and it will not affect the minimum number of coins.
>>Five Steps of Dynamic Rules
1. Determine the meaning of the dp array and subscripts
dp[j]: The minimum number of coins required to make up the total amount j is dp[j]
2. Determine the recursion formula
The minimum number to make up the total amount of j - coins[i] is dp[j - coins[i]] , then you only need to add one coin coins[i] , which is dp [j - coins[i]] + 1. dp[j] (consider coins[i]) , then dp[j] should be the smallest of all dp[j - coins[i]] + 1
Recursion formula: dp[j] = min(dp[j - coins[i]] + 1, dp[j]);
3.dp array initialization
dp[0] = 0; means that the number of coins required for a total amount of 0 must be 0
What about the values corresponding to other subscripts? Due to the min(dp[j-coins[i]] + 1,dp[j]) comparison process, if the initial value we set is smaller, it may be overwritten by the initial value, so dp[j] must be initialized to The largest number. That is INT_MAX
vector<int> dp(amount + 1, INT_MAX);
dp[0] = 0;
4. Determine the traversal order
- Method 1: Traverse the items first and then the backpack (find the number of combinations)
- Method 2: Traverse the backpack first and then the items (find the number of permutations)
What is required in this question is the minimum number of coins, regardless of the order. So either method 1 or method 2 is fine! ! !
5. Derivation of dp array with examples
Enter: coins = [1,2,5],amount = 5. Use the traversal order of method 1, that is, traverse items first and then traverse the backpack.
Use method 1 to traverse:
class Solution {
public:
int coinChange(vector<int>& coins, int amount) {
vector<int> dp(amount+1,INT_MAX);
dp[0] = 0;
// 组合数 时间复杂度:O(n * amount),其中 n 为 coins 的长度;空间复杂度:O(amount)
for(int i=0;i<coins.size();i++) { // 物品
for(int j=coins[i];j <= amount;j++) { // 背包
if (dp[j - coins[i]] != INT_MAX) // // 如果dp[j - coins[i]]是初始值则跳过
dp[j] = min(dp[j],dp[j-coins[i]] + 1);
}
}
if(dp[amount] == INT_MAX) return -1;
return dp[amount];
}
};
- Time complexity: O(n * amount), where n is the length of coins
- Space complexity: O(amount)
Use method 2 to traverse:
class Solution {
public:
int coinChange(vector<int>& coins, int amount) {
vector<int> dp(amount+1,INT_MAX);
dp[0] = 0;
// 排列数 时间复杂度:O(n * amount),其中 n 为 coins 的长度;空间复杂度:O(amount)
for(int j = 0;j <= amount; j++) { // 背包
for(int i = 0;i < coins.size(); i++) { // 物品
if(j >= coins[i] && dp[j - coins[i]] != INT_MAX)
dp[j] = min(dp[j],dp[j-coins[i]] + 1);
}
}
if(dp[amount] == INT_MAX) return -1;
return dp[amount];
}
};
- Time complexity: O(n * amount), where n is the length of coins
- Space complexity: O(amount)
Reference and recommended articles and videos:
Code Random Record (programmercarl.com)
Class screenshots from Code Caprice: