【发布时间】:2022-01-06 20:04:42
【问题描述】:
我刚刚解决了子集和问题:
给定一个大小为
N的整数数组nums。还给你一个整数B,你需要找出nums中是否存在一个子集,其和为B。如果存在子集,则返回1,否则返回0。约束是:
1 <= N <= 100;1 <= nums[i] <= 100;1 <= B <= 10^5;
我解决这个问题的方法如下(0/1背包):
vector<int> n;
int t;
unordered_map<string, long long> m;
int helper(int i, int sum) {
if(i>=n.size()) return sum==t;
string str=to_string(i)+"-"+to_string(sum);
if(m.count(str)) return m[str];
int val=helper(i+1, sum+n[i]);
val=max(val, helper(i+1, sum));
return m[str]=val;
}
int Solution::solve(vector<int> &nums, int B) {
n=nums;
t=B;
m.clear();
return helper(0,0);
}
这得到“接受”。但是,请注意nums 中的所有值都是正数;所以IMO总和只会保持不变/继续增加。 i 也在继续增加。因此,我们永远不会遇到以前存储在记忆表中的值。
但是,如果我删除记忆,它会导致一些大型测试用例的错误答案。我错过了什么?任何递归调用都会遇到以前的状态吗?
【问题讨论】:
-
这样的问题,你不能提供导致失败的输入,可能是题外话:meta.stackoverflow.com/questions/270585/…。为了创建minimal reproducible example 并提出可接受的问题,您可能需要做更多的工作来开发自己的测试用例。
-
@NateEldredge,谢谢。我只是希望在我的理解中发现我们从未遇到过以前计算的值的逻辑缺陷。
-
不是很相关,但是
string str=to_string(i)+"-"+to_string(sum);:你知道std::pair吗? -
int val=helper(i+1, sum+n[i]); val=max(val, helper(i+1, sum));第二次调用得到的sum值比第一次要小,所以sum肯定不是单调递增的。 -
如果您的数组是
2,4,1,5, ...,并且您在跳过 1,5 的同时选择了 2,4,那么您有一个 i=4 和 sum=6 的子问题。另一方面,如果你跳过 2,4 并选择 1,5,那么子问题是 i=4 和 sum=6。
标签: c++ algorithm recursion dynamic-programming memoization