考虑子集总和(SUSU)问题,我需要编写类中显示的解决方案的变体,该变体还将打印汇总哪些权重以达到给定的总和。例如,如果:
sum=12;
int[] weights={1,7,9,3};
输出将是:0011也就是说,对于权重中的每个值,如果添加了该值,则我们将其写入“ 1”,否则将其写入“ 0”。
在朋友的帮助下,我编写了以下代码:
public static void main(String[] args) {
int[] arr={9,1,7,3};
System.out.println(Arrays.toString(SubsetSum(arr,12)));
}
public static int[] SubsetSum(int[] arr, int sum){
int[] output= new int[arr.length];
return SubsetSum(arr,sum, 0, output);
}
public static int[] SubsetSum(int[] arr, int sum, int index, int[]weights){
int[] output= new int[arr.length];
if(sum==0)
return weights;
if(sum<0 | index>=arr.length)
return output;
weights[index]=0;
int[] arr1= SubsetSum(arr,sum,index+1, weights);
weights[index]=1;
int[]arr2=SubsetSum(arr,sum-arr[index],index+1,weights);
boolean isZero=true;
for(int i=0; i<arr1.length & isZero; i=i+1)
if(arr1[i]!=0)
isZero=true;
if(isZero)
return arr2;
else
return arr1;
}
我希望SubsetSum(arr,12)的输出为[1、0、0、1],但实际输出为[0、0、0、0]。 我知道为什么它会从我的代码中返回此输出,但是我不知道如何解决它。
答案 0 :(得分:0)
我更改了返回结果的方法。现在使用的项目以used
参数的位进行编码。
Main打印项目的索引(如果失败,则不打印任何内容)-例如1,2,3
,即1 + 7 + 13
我对Java不熟悉,因此请代表结果以便更好地查看(也许像inttobinary
之类的东西)
public static void main(String[] args) {
int[] arr={9,1,7,13,3};
int i = 0;
int res = SubsetSum(arr, 21, 0, 0);
while (res > 0) {
if ((res & 1) > 0)
System.out.println(i);
i++;
res >>= 1;
}
}
public static int SubsetSum(int[] arr, int sum, int index, int used){
if(sum==0)
return used;
if(sum<0 | index>=arr.length)
return 0;
int a = SubsetSum(arr,sum,index+1, used);
int b = SubsetSum(arr,sum-arr[index],index+1, used | (1 << index));
if (a > 0)
return a;
else
return b;
}
}
P.S。代码中存在缺陷:
isZero
从未更改。
如果您更正逻辑以返回非零数组,则它将用全1填充-可能是因为weights[index]=1;
通过公共引用更改了同一数组实例(不知道Java术语)。在我的代码中,每个递归级别都有一个used
实例,修改其位不会影响其他分支中的值。