我试图用递归解决方案来解决子集求和问题,但是为了使它更有效率,我试图将memoization放入其中。但是,没有memoization的代码会提供正确的解决方案,但是通过memoization它无法正常工作。
public int subsetSum(int num[], int idx, int expecedSum, int dp[]) {
if (expecedSum == 0) {
return 1;
}
else if (idx < 0 || expecedSum < 0) {
return 0;
}
else {
if (dp[expecedSum] == -1) {
int x = subsetSum(num, idx - 1, expecedSum, dp);
int y = subsetSum(num, idx - 1, expecedSum - num[idx], dp);
dp[expecedSum] = (x == 1 || y == 1) ? 1 : 0;
}
return dp[expecedSum];
}
}
public static void main(String args[]) {
Solution s = new Solution();
int num[] = new int[]{1, 2, 3, 4, 5, 6, 7};
int sum = 0;
int n = new Scanner(System.in).nextInt();
int dp[] = new int[n + 1];
for (int i = 0; i < dp.length; i++) {
dp[i] = -1;
}
dp[0] = 1;
s.subsetSum(num, num.length - 1, n, dp);
}
有人可以帮我解释为什么这不起作用吗?
如果我输入n = 14,那么理想情况下dp [14]应该包含1,但它不包含1.
答案 0 :(得分:0)
总和不足以描述国家。对(总和,指数)是。如果您使temp <= sum - array[i];
数组dp
数组并在(max_sum + 1) x num.length
方法中对(idx, expectedSum)
对应用了memoization,则可行。
答案 1 :(得分:0)
已经好几年了,但是今天可能对某人有所帮助。 想法是同时采用状态-意味着一次将当前元素包括在总和中,一次将当前元素排除在总和中。然后将这些值取OR(||)并存储在缓存中。
代码看起来像这样-
#include <iostream>
#include <vector>
using namespace std;
bool sumExists(vector<int> & a, int cursum, int n, vector<vector<int>> &dp) {
if(n==0 && cursum != 0)
return 0;
if(cursum==0)
return 1;
if(dp[n][cursum] != -1) {
return dp[n][cursum];
}
int newsum = cursum - a[n-1];
bool returnval = false;
if(newsum>=0) {
dp[n][newsum] = sumExists(a, newsum, n-1, dp);
dp[n][cursum] = sumExists(a, cursum, n-1, dp);
returnval = dp[n][newsum] || dp[n][cursum];
} else {
dp[n][cursum] = sumExists(a, cursum, n-1, dp);
returnval = dp[n][cursum];
}
return returnval;
}
int main() {
// your code goes here
vector<int> a{2,0,7,8,10};
int n = a.size();
int sum = 11;
vector<vector<int>> dp(n+1, vector<int>(sum+1, -1));
for(int i=0;i<=n;++i) {
dp[i][0]=true;
}
for(int i=1;i<=sum;++i) {
dp[0][i]=false;
}
if(sumExists(a, sum, n, dp)) {
cout<<"YES"<<endl;
} else {
cout<<"NO"<<endl;
}
}