简体   繁体   English

查找具有给定总和的数字子集

[英]Finding Subsets of Numbers with a Given Sum

Using recursion, write a program that given a list of integer numbers and a given sum, will find all the subsets of the numbers whose total is that given sum. 使用递归,编写一个给出整数列表和给定总和的程序,将找到总数是给定总和的数字的所有子集。 Count the number of subsets found. 计算找到的子集数。 If no subset exists, you should indicate that no solution is found. 如果不存在子集,则应指明未找到解决方案。 For example, given the list 6, 13, 3, 3 and the sum is 19, your program should find two solutions: 例如,给定列表6,13,3,3并且总和为19,您的程序应该找到两个解决方案:

6 + 13 = 19
13 + 3 + 3 = 19

Limit the number of integers in the input list to a maximum of 20 integers. 将输入列表中的整数数限制为最多20个整数。 Accept positive integers only and use 0 to mark the end of list. 仅接受正整数,并使用0标记列表的结尾。 The following is a sample run: 以下是示例运行:

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

this is my code,but it is only finding one sub set, i want to find all sub sets. 这是我的代码,但它只找到一个子集,我想找到所有的子集。 any help? 任何帮助?

 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) ;
    }
}

Your main issues are that you: 您的主要问题是:

  • are returning right away once you find the solution 一旦找到解决方案,马上就会回来
  • are only considering numbers from left to right for your solution 只考虑从左到右的数字为您的解决方案

What you need to do is consider all possible sublists of the original list for your solution eg, for a list of [A, B, C, D] , the solution may be [A, C, D] . 您需要做的是考虑解决方案原始列表的所有可能的子列表,例如,对于[A, B, C, D] ,解决方案可能是[A, C, D] So a good place to start is some code that is able to create all sublists of a list. 因此,一个好的起点是一些能够创建列表的所有子列表的代码。 To do this you will need to have a Set of Lists where you can aggregate all possibilities. 要做到这一点,您需要有一组列表,您可以聚合所有可能性。 Here is an example that does this by removing elements from a copy of the original list, but there are many ways to do this: 下面是一个通过从原始列表的副本中删除元素来执行此操作的示例,但有很多方法可以执行此操作:

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);
    }
}

If you run this, you will see by the output that we are finding all the sublists of the original input list [4, 1, 3, 2] . 如果你运行它,你会看到输出我们正在查找原始输入列表[4, 1, 3, 2] 4,1,3,2]的所有子列表。

Output check: 输出检查:

[[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]]

Then all that is left is to only add sublists that add up to the requested number, instead of adding all possibilities. 然后剩下的就是只添加加起来所需数量的子列表,而不是添加所有可能性。

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);
    }
}

Answer check: 答案检查:

[[3, 2], [4, 1]]

There are some optimizations you can still make with this code that I will leave up to you. 您仍然可以使用此代码进行一些优化,我将留给您。

The basic problem is that you've returned the wrong information: you need all of the solutions found, but you've returned only a boolean according to whether you succeeded. 基本问题是您返回了错误的信息:您需要找到所有解决方案,但根据您是否成功,您只返回了一个布尔值。 Instead, you need to construct a list of solutions. 相反,您需要构建一个解决方案列表。

Base cases: 基本情况:

  • if target = 0, you succeeded. 如果target = 0,你就成功了。 Print the solution and increment the counter. 打印解决方案并递增计数器。
  • else if target < 0, you failed. 否则,如果目标<0,则表示失败。
  • else if you have no items left, you failed. 否则,如果你没有剩下的物品,你就失败了。

Recursion cases: 递归案例:

You did okay on the basic idea: recur both with and without subtracting the current number. 你对基本想法没问题:在有和没有减去当前数字的情况下重复。 However, you could also pass down a list of the numbers used in this branch -- that way, when you hit the bottom, you can print the list. 但是,您也可以传递此分支中使用的数字列表 - 这样,当您点击底部时,您可以打印列表。 There are other ways to handle this step, but I think this is simplest for your application. 还有其他方法可以处理这一步骤,但我认为这对您的应用程序来说是最简单的。 If you're not allowed to change the signature of SubSetSum, then use that as a "wrapper" and call your real function from there, starting with an empty list. 如果您不允许更改SubSetSum的签名,则将其用作“包装器”并从那里调用您的实际函数,从空列表开始。

Does this get you moving? 这会让你感动吗? You could also check the dozens of previous questions about this problem. 您还可以查看以前有关此问题的几十个问题。

My Dp Solution :- 我的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]);
        }
    }

Time coplx. 时间coplx。 O(N*target) space complx. O(N *目标)空间complx。 O(N) 上)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 回溯 - 给定一组数字,找到总和等于 M 的所有子集(给定 M) - Backtracking - Given a set of numbers, find all the subsets with a sum equal to M (M is given) 在数组中找到总和等于给定数字的所有数字对? - finding all pairs of numbers in an array whose sum equals a given number? 查找三个数字之和可被给定数字整除的数字 - Finding three numbers whose sum is divisible by a given number 查找重复编号的所有组合以达到给定的总和 - Finding all combinations of duplicates numbers to reach a given sum 查找大小为N的数字的组合,这些数字的和等于给定的数字 - Finding a combination of numbers of size N that sum up to a given number 通过回溯查找求和 n 的所有子集 - Finding all the subsets that sum n via backtracking 在 java 中查找给定集合的所有子集,并按此顺序 - finding all subsets of a given set in java and in this order 动态编程-打印给定总和的所有子集 - dynamic programming - print all subsets with the given sum 在字符串中查找 NUMBERS 的总和? - Finding the sum of NUMBERS in a string? 给定一个整数数组和一个总和,任务是找出给定数组的子集是否存在总和等于给定总和的子集 - Given an array of integers and a sum, the task is to find if there exists a subsets of given array with sum equal to given sum
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM