leetcode 377
来源:9-7 面试中的0-1背包问题 Partition Equal Subset Sum
pfco
2019-07-24
//动态规划
//时间复杂度O(n*target)
//空间复杂度O(n*target)
//状态是考虑放入第i个数字
//由此状态转移方程为f(i,target)=f(i-1,target)+f(i-1,target-nums[i])+f(i,target-nums[i])
public int DongCombinationSum4(int[] nums, int target) {
int n=nums.length;
if(n==0||target<0){
return 0;
}//如果没有数字或者目标数字小于0,返回0就可以了
int[][]memo=new int[n][target+1];//表示范围[0,index]的数字组成target的所有的方案
for(int j=0;j<=target;j++){
if(j%nums[0]==0){
memo[0][j]=1;
}else{
memo[0][j]=0;
}
}
for(int i=1;i<n;i++){
for(int j=0;j<=target;j++){
if(j>=nums[i]){
memo[i][j]=memo[i-1][j]+memo[i-1][j-nums[i]]+memo[i][j-nums[i]];
/*
这里我认为的是和完全背包问题是一样的,就是对于[0-i]的目标为j,组成它的情况
就是要么不取第i个数字,那就是对于[0,i-1]目标为j的情况,以及要么取第i个数字
那就是对于[0,i-1]目标为j-nums[i]的情况,还有一种就是对于[0,i],目标为j-nums[i]
的情况,这三种情况的和就是最后的结果,但是答案和预想的不一样
*/
}else{
memo[i][j]=memo[i-1][j];
}
}
}
return memo[n-1][target];
}
老师麻烦看一下,我这个问题的思路出错在哪里了?
写回答
2回答
-
和背包问题不一样。最大的区别是,背包问题你是没有顺序的。你只要让背包价值最大就好了。按照什么顺序放物品不重要。
而这个问题,恰恰让你记的顺序,就是和放物品的顺序相关的。
我的参考代码如下:https://github.com/liuyubobobo/Play-Leetcode/blob/master/0377-Combination-Sum-IV/cpp-0377/main2.cpp
主体逻辑是这样的:
memo[0] = 1; for(int i = 1; i <= target; i++) // 对于每一个新的目标i,都看一遍nums[0...n-1]所有数字 for(int j = 0; j < n; j ++) if(nums[j] <= i) // 用当前的nums[j] 加上能凑成 i - nums[j] 的方法数 memo[i] += memo[i - nums[j]];
另外,这个问题的结果可能整形溢出,在这种情况下返回-1就可以AC。题目中对此似乎没有注明。我不确定是不是C++特有的问题。所以上面的参考代码链接你会看到循环内对整形溢出的判断。单位了说明逻辑,上的代码不包含。
再仔细体会一下?:)
继续加油!:)
032022-07-27 -
pfco
提问者
2019-07-24
老师,我认为这个问题我是忽略了顺序性这个东西,但是确实不知道应该怎么改,逻辑上感觉没什么问题
00
相似问题