使用递归,编写一个给出整数列表和给定总和的程序, 将找到总数为给定总和的数字的所有子集。计算找到的子集数。如果不存在子集,则应指明未找到解决方案。例如,给定列表6,13,3,3并且总和为19,您的程序应该找到两个 解决方案:
6 + 13 = 19
13 + 3 + 3 = 19
将输入列表中的整数数限制为最多20个整数。接受 仅正整数,并使用0来标记列表的结尾。 以下是一个示例运行:
Enter positive integers terminated with 0: 6 13 3 3 0
Enter the desired sum: 19
Solution 1:6 +13 =19
Solution 2: 13 +3 +3 =19
Found 2 solutions
这是我的代码,但它只找到一个子集,我想找到所有子集。有什么帮助吗?
public static boolean SubSetSum(int start, int[] nums, int target) {
if (start >= nums.length) {
return (target == 0);
}
if (SubSetSum(start + 1, nums, target - nums[start])) {
System.out.println( nums[start] );
return true;
}
if (SubSetSum(start + 1, nums, target)) {
return true;
}
return false;
}
public static void main(String[] args) {
int[] mySet = {4,1,3,2};
int sum = 5;
System.out.println("The Goal is : " + sum);
SubSetSum(0,mySet, sum) ;
}
}
答案 0 :(得分:1)
您的主要问题是:
您需要做的是考虑解决方案原始列表的所有可能的子列表,例如,对于[A, B, C, D]
的列表,解决方案可能是[A, C, D]
。因此,一个好的起点是一些能够创建列表的所有子列表的代码。要做到这一点,您需要有一组列表,您可以聚合所有可能性。下面是一个通过从原始列表的副本中删除元素来执行此操作的示例,但有很多方法可以执行此操作:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
class ResursionTest {
public static void findSubsets(Set<List<Integer>> allSubsets, List<Integer> nums) {
if (nums.size() == 0) {
return;
}
// add the current list as a possibility
allSubsets.add(new ArrayList<>(nums));
// then add a possibility that has one less
for (int i = 0; i < nums.size(); i++) {
final List<Integer> subset = new ArrayList<>(nums);
subset.remove(i);
findSubsets(allSubsets, subset);
}
}
public static void main(String[] args) {
final Integer[] array = {4, 1, 3, 2};
final HashSet<List<Integer>> allSubsets = new HashSet<>();
findSubsets(allSubsets, Arrays.asList(array));
System.out.println(allSubsets);
}
}
如果你运行它,你会看到输出我们正在查找原始输入列表[4, 1, 3, 2]
的所有子列表。
输出检查:
[[3, 2], [1], [4, 3], [2], [3], [1, 2], [4, 3, 2], [1, 3], [4], [4, 1, 2], [4, 1, 3], [4, 1, 3, 2], [4, 1], [1, 3, 2], [4, 2]]
然后剩下的就是只添加加起来所需数字的子列表,而不是添加所有可能性。
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
class ResursionTest {
public static void findSubsets(Set<List<Integer>> allSubsets, List<Integer> nums, int sum) {
if (nums.size() == 0) {
return;
}
int currentSum = 0;
for (Integer num : nums) {
currentSum += num;
}
// does the current list add up to the needed sum?
if (currentSum == sum) {
allSubsets.add(new ArrayList<>(nums));
}
for (int i = 0; i < nums.size(); i++) {
final List<Integer> subset = new ArrayList<>(nums);
subset.remove(i);
findSubsets(allSubsets, subset, sum);
}
}
public static void main(String[] args) {
int sum = 5;
final Integer[] array = {4, 1, 3, 2};
final HashSet<List<Integer>> allSubsets = new HashSet<>();
findSubsets(allSubsets, Arrays.asList(array), sum);
System.out.println(allSubsets);
}
}
答案检查:
[[3, 2], [4, 1]]
您仍然可以使用此代码进行一些优化,我将留给您。
答案 1 :(得分:0)
基本问题是您返回了错误的信息:您需要找到所有解决方案,但根据您是否成功,您只返回了一个布尔值。相反,您需要构建一个解决方案列表。
基本情况:
递归案例:
你对基本想法没问题:在有和没有减去当前数字的情况下重复。但是,您也可以传递此分支中使用的数字列表 - 这样,当您点击底部时,您可以打印列表。还有其他方法可以处理这一步骤,但我认为这对您的应用程序来说是最简单的。如果您不允许更改SubSetSum的签名,那么将其用作“包装器”并从那里调用您的实际函数,从空列表开始。
这会让你感动吗?您还可以查看以前有关此问题的几十个问题。
答案 2 :(得分:0)
我的Dp解决方案: -
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int t = sc.nextInt();
while(t-->0){
int n = sc.nextInt();
int arr[] = new int[n];
for(int i = 0;i<n;i++){
arr[i] = sc.nextInt();
}
int target = sc.nextInt();
int dp[] = new int[target+1];
dp[0] = 1;
int currSum = 0;
for(int i = 0;i<n;i++){
currSum += arr[i];
for(int j = Math.min(currSum,target);j>= arr[i];j--){
dp[j] += dp[j-arr[i]];
}
}
System.out.println(dp[target]);
}
}
时间coplx。 O(N *目标)空间complx。 O(N)