目录
一、518. 零钱兑换 II
1.题目描述
2.解题思路
- 问组成所给金额amount的方法最多有多少种?这里每种面额的钞票不限次数使用,抽象为完全背包问题。
- 装满amount重量的背包,物品不限次数使用,最多有多少种方法。
- 注意点,这里的遍历顺序一定是先物品,再背包。(因为这里是组合问题,对输出元素的顺序没有要求)
3.代码实现(背包思想)
class Solution {
public:
int change(int amount, vector<int>& coins) {
vector<int> dp(amount+1,0);
//dp数组含义:重量为i的背包最多有多少种组成方法
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];
}
};
4.代码实现(回溯思想)
class Solution {
public:
int result;
void backtracking(const vector<int>& coins,int startIndex,int sum,int amount){
if(sum > amount)
return ;
if(sum == amount)
result++;
//单层逻辑
for(int i = startIndex;i < coins.size();i++){
sum += coins[i];
//递归操作
backtracking(coins,i,sum,amount);
//回溯操作
sum -= coins[i];
}
}
int change(int amount, vector<int>& coins) {
backtracking(coins,0,0,amount);
return result;
}
};
二、377. 组合总和 Ⅳ
1.题目描述
给你一个由 不同 整数组成的数组 nums
,和一个目标整数 target
。请你从 nums
中找出并返回总和为 target
的元素组合的个数。
题目数据保证答案符合 32 位整数范围。
示例 1:
输入:nums = [1,2,3], target = 4 输出:7 解释: 所有可能的组合为: (1, 1, 1, 1) (1, 1, 2) (1, 2, 1) (1, 3) (2, 1, 1) (2, 2) (3, 1) 请注意,顺序不同的序列被视作不同的组合。
示例 2:
输入:nums = [9], target = 3 输出:0
2.解题思路
- 和518.零钱兑换||问题差不多,只不过这里是排列问题。
3.代码实现
class Solution {
public:
int combinationSum4(vector<int>& nums, int target) {
vector<int> dp(target+1,0);
//dp数组含义:最大容量为j的背包,由这些不限次数的物品装满最多有多少种方法
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]];
}
}
for(int i = 0;i < dp.size();i++)
cout << dp[i] << ' ';
return dp[target];
}
};