我正在尝试使用2d数组作为缓存来实现自上而下的Memoization方法来解决Subset-Sum问题。下面是我到目前为止尝试过的代码。但是我没有从代码中获得预期的结果。
public static void main(String []args){
int set[] = {3, 34, 4, 12, 5, 2};
int sum = 9;
int n = set.length;
if (isSubsetSum(set, n, sum) == true)
System.out.println("Found a subset with given sum");
else
System.out.println("No subset with given sum");
}
static boolean isSubsetSum(int set[], int n, int sum){
int[][] dp = new int[n][sum+1];
for(int i = 0 ; i < n ; i++)
for(int j = 0 ; j < sum ; j++)
dp[i][j] = -1;
for(int i = 0 ; i < n ; i++){
dp[i][0] = 1;
}
return isSubsetSum1(set,n-1,sum,dp);
}
static boolean isSubsetSum1(int set[], int n, int sum,int[][] dp)
{
// Base Cases
if (sum == 0)
return true;
if (n == 0 && sum != 0)
return false;
if(dp[n][sum] == -1){
dp[n][sum] = isSubsetSum1(set, n-1, sum,dp) ? 1 : 0;
if(sum > set[n-1]){
boolean result = isSubsetSum1(set, n-1, sum,dp) ||
isSubsetSum1(set, n-1, sum-set[n-1],dp);
dp[n][sum] = result ? 1 : 0;
}
}
return dp[n][sum] == 1 ? true : false;
}
请帮助我找到代码中的逻辑错误。
答案 0 :(得分:0)
您可以尝试一种不需要递归的动态编程解决方案。基本上你必须根据一些合同建立一个带有回顾的矩阵(2d数组缓存)。
我试图用Kotlin解决问题,找出你给出整数数组的子集组合数。它在2 3 4 5 12 34
的情况下产生一个矩阵,告诉你每个预期数量有多少组合。预期的数字位于最左侧列的下方示例中:
2 3 4 5 1234
0 1 1 1 1 1 1
1 0 0 0 0 0 0
2 1 1 1 1 1 1
3 0 1 1 1 1 1
4 0 0 1 1 1 1
5 0 1 1 2 2 **2**
6 0 0 1 1 1 1
7 0 0 1 2 2 2
8 0 0 0 1 1 **1**
9 0 0 1 2 2 **2**
如果您阅读此表,它会告诉您,对于5的总和,给定完整数组(2 3 4 5 12 34
),您有2个子集,8个只有1个,9个2个,等等。这些示例在上面突出显示
您可以使用此Kotlin代码构建此数组:
fun subsetTable(coinsA: IntArray, total: Int): Array<IntArray> {
val coins = coinsA.sorted()
val size = coins.size
val table = Array(total + 1, { IntArray(size) })
(0 until size).forEach { table[0][it] = 1 }
(1..total).forEach { row ->
(0 until coins.size).forEach { col ->
if (col == 0) {
table[row][col] = if (row == coins[0]) 1 else 0
} else {
val x = if (row - coins[col] >= 0) table[row - coins[col]][col - 1] else 0
val y = if (col >= 1) table[row][col - 1] else 0
table[row][col] = x + y
}
}
}
return table
}
免责声明:我没有广泛测试代码,因此可能存在一些问题。
如果您有兴趣,我可以将此代码转换为Java。