518. 零钱兑换 II
思路:本题就是完全背包的形式,元素可以重复利用
一维数组的形式,先遍历物品,再遍历背包容量.得到的是组合数,遍历顺序不能换 dp[j]+=dp[j-coins[i]]
二维数组的遍历形式两层for循环可以调换 dp[i][j] = dp[i - 1][j] + dp[i][j - coins[i]]
如果求组合数就是外层for循环遍历物品,内层for遍历背包。
如果求排列数就是外层for遍历背包,内层for循环遍历物品。
这里是求组合数
代码:
class Solution {
public int change(int amount, int[] coins) {
int[] dp=new int[amount+1];
//初始化dp数组,默认当金额为零时,只有一种情况
dp[0]=1;
for(int i=0;i<coins.length;i++){
for(int j=coins[i];j<=amount;j++){
dp[j]+=dp[j-coins[i]];
}
}
return dp[amount];
}
377. 组合总和 Ⅳ
思路:其实这题的思路和上一题差不多,只是要先遍历背包容量,在遍历物品数量(即求排列数),只是在最终结果上由差别,就是这里的排列,只要顺序不同,就当成一个新的集合。
这里是求排列数
代码:
class Solution {
public int combinationSum4(int[] nums, int target) {
int[] dp=new int[target+1];
dp[0]=1;//targe=0的个数只有一个
for(int j=0;j<=target;j++){//先遍历背包容量
for(int i=0;i<nums.length;i++){//再遍历物品数量
if(j>=nums[i]){
dp[j]+=dp[j-nums[i]];
}
}
}
return dp[target];
}
}