518. 零钱兑换 II - 力扣(Leetcode)
思路:
-
这道题是经典完全背包问题,但不是纯完全背包,因为纯完全背包的情况是物品数量无限,求一定背包容量下能容纳的最大价值。而这道题求的是能填满一定背包容量不同的组合数量,且每个物品数量是无限的。与纯完全背包不同的是状态转移方程不同,纯完全背包问题的递推公式是
dp[j] = max(dp[j], dp[j - nums[i] + values[i])
,而本题的递推公式是dp[j] += dp[j - nums[i]]
-
-
确定dp数组以及下标的含义
- dp[j]的定义为:凑成金额为j的背包的组合数量
-
确定递推公式
- 状态转移方程为
dp[j] += dp[j - coins[i]];
- 状态转移方程为
-
dp数组如何初始化
vector<int> dp(amount + 1, 0);
-
确定遍历顺序
// 本题采用的是先遍历物品再遍历背包,如果先遍历背包再遍历物品的话[1, 5]和[5, 1]会被认为不同的种类,但本题认为这是同一种。在求排列数量,即把[1, 5]和[5, 1]当作不同的种类时才先遍历背包再遍历物品 for(int i = 0; i < coins.size(); ++i) { for(int j = coins[i]; j <= amount; ++j) { dp[j] += dp[j - coins[i]]; } }
-
我的AC代码
// 时间复杂度O(m x n),空间复杂度O(n)
// m代表amount
class Solution {
public:
int change(int amount, vector<int>& coins) {
vector<int> dp(amount + 1, 0);
dp[0] = 1;
for(int i = 0; i < coins.size(); ++i) {
for(int j = coins[i]; j <= amount; ++j) {
dp[j] += dp[j - coins[i]];
}
}
return dp[amount];
}
};
标准答案
// 时间复杂度O(m x n),空间复杂度O(n)
// m代表amount
class Solution {
public:
int change(int amount, vector<int>& coins) {
vector<int> dp(amount + 1, 0);
dp[0] = 1;
for (int i = 0; i < coins.size(); i++) { // 遍历物品
for (int j = coins[i]; j <= amount; j++) { // 遍历背包
dp[j] += dp[j - coins[i]];
}
}
return dp[amount];
}
};
377. 组合总和 Ⅳ - 力扣(Leetcode)
思路:
-
本题也是完全背包类问题,因为物品数量无限,所以遍历背包的时候要从小到大遍历,又因为求的是排列数量,所以进行遍历的时候要先遍历背包再遍历物品
-
-
确定dp数组以及下标的含义
- dp[j]的定义为:target为j的时候所有可能的排列数量
-
确定递推公式
- 状态转移方程为
dp[j] += dp[j - nums[i]];
- 状态转移方程为
-
dp数组如何初始化
vector<int> dp(target + 1, 0);
-
确定遍历顺序
for(int j = 0; j <= target; ++j) { for(int i = 0; i < nums.size(); ++i) { if (j - nums[i] >= 0 && dp[j] < INT_MAX - dp[j - nums[i]]) { dp[j] += dp[j - nums[i]]; } } }
-
我的AC代码
// 时间复杂度O(n2),空间复杂度O(n)
class Solution {
public:
int combinationSum4(vector<int>& nums, int target) {
vector<int> dp(target + 1, 0);
dp[0] = 1;
for(int j = 0; j <= target; ++j) {
for(int i = 0; i < nums.size(); ++i) {
if (j - nums[i] >= 0 && dp[j] < INT_MAX - dp[j - nums[i]]) {
dp[j] += dp[j - nums[i]];
}
}
}
return dp[target];
}
};
标准答案
// 时间复杂度O(n2),空间复杂度O(n)
class Solution {
public:
int combinationSum4(vector<int>& nums, int target) {
vector<int> dp(target + 1, 0);
dp[0] = 1;
for (int i = 0; i <= target; i++) { // 遍历背包
for (int j = 0; j < nums.size(); j++) { // 遍历物品
if (i - nums[j] >= 0 && dp[i] < INT_MAX - dp[i - nums[j]]) {
dp[i] += dp[i - nums[j]];
}
}
}
return dp[target];
}
};
Comments NOTHING