今天进入完全背包。
Leetcode 518. 零钱兑换 II
题目链接 518 零钱兑换 II
由于是可以选取多个元素,所以是完全背包,要注意在遍历顺序中前序遍历,其他的和前面的目标数这个题目类似,要理解dp[j]+=dp[j-nums[i]]的来源。(总体来是还是比较难想的)
下面上代码:
cpp
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] += dp[j-coins[i]];
}
}
return dp[amount];
}
};
Leetcode 377. 组合总和 Ⅳ
题目链接 377 组合总和 Ⅳ
本题目就是上个题目的改版,这个要求的是排列数,所以我们只需先便利背包,在遍历物品即可(原因卡哥讲过),还要注意C++测试用例有两个数相加超过int的数据,所以需要在if里加上dp[i] < INT_MAX - dp[i - num]。
直接上代码:
cpp
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]&& dp[i] < INT_MAX - dp[i - nums[j]]){//C++测试用例有两个数相加超过int的数据,所以需要在if里加上dp[i] < INT_MAX - dp[i - num]。
dp[i] += dp[i-nums[j]];
}
}
}
return dp[target];
}
};
end