当前位置: 首页 > 知识库问答 >
问题:

用给定的和查找数字子集

施令秋
2023-03-14

使用递归,编写一个给定整数列表和给定和的程序,将找到总数为给定和的所有数字子集。计算找到的子集数。如果不存在子集,则应指示未找到解决方案。例如,给定列表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) ;
    }
}

共有3个答案

李捷
2023-03-14

我的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]);
        }
    }

时间复合体。O(N*目标)空间复合体。O(N)

赵夕
2023-03-14

基本问题是您返回了错误的信息:您需要找到的所有解决方案,但根据您是否成功,您只返回了一个布尔值。相反,您需要构建一个解决方案列表。

基本情况:

  • 如果目标=0,则成功。打印解决方案并增加计数器
  • 否则,如果目标

递归情况:

您在基本思想上做得很好:使用和不使用当前数字进行重复。然而,您也可以传递此分支中使用的数字列表——这样,当您到达底部时,就可以打印该列表。有其他方法可以处理此步骤,但我认为这对于您的应用程序来说是最简单的。如果不允许更改SubSetSum的签名,则将其用作“包装器”,并从那里调用真正的函数,从空列表开始。

这能让你搬家吗?您还可以查看之前关于此问题的数十个问题。

王才英
2023-03-14

您的主要问题是:

  • 找到解决方案后立即返回

您需要做的是为您的解决方案考虑原始列表的所有可能的子列表,例如,对于<代码>[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);
    }
}

如果运行此操作,您将从输出中看到,我们正在查找原始输入列表的所有子列表。

输出检查:

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

对于这段代码,您仍然可以进行一些优化,我将留给您。

 类似资料:
  • 问题内容: 给定一个非负整数数组和一个数字。您需要打印总和等于给定整数的子数组的所有开始和结束索引。 例如 : Explanation : [3, 6] [9], [9,0] These all are the subarrays with their sum equal to 9. 问题答案: 解决这个问题的基本蛮力方法是生成给定数组的所有子数组,然后遍历生成的子数组并计算总和,如果这个总和等于

  • 认为 例1:数字是37,数字之和是37=10 例2:数字是1000,数字之和是1。 我的第一种方法是将数字转换成字符串,然后再转换成字符数组。有了它,我可以使用流,在其中我将字符转换为int值,让我执行求和。 但是流API中有什么实用方法可以改进它吗?

  • 问题内容: 我正在尝试编写一种算法,用于在给定的子矩阵中查找子矩阵。为了解决这个问题,我编写了以下代码: 这段代码可以正常工作,但是我不确定这是问题的确切解决方案还是可以解决。请提供您的专家意见。提前致谢。 问题答案: 该算法对4×4矩阵和2×2子矩阵进行了硬编码。否则,它看起来像蛮力算法。 我会这样表示: 如果您想要更有效的方法,建议您将它们压扁,如下所示: 并在此序列中搜索以下模式: 使用标准

  • 循环子串: null null null null 示例2: 返回:=>的出现不相邻重复,相邻重复两次 示例3: null null 返回,因为没有重复的相邻子字符串 实现该算法的最佳方法是什么?

  • 问题内容: 说我有一个清单。我想找到3个最接近的数字,例如6.5。然后返回的值将是。 在python中找到一个最接近的数字并不是那么棘手,可以使用 但是我试图不绕这个循环找到k个最接近的数字。有pythonic方法可以完成上述任务吗? 问题答案: 简短的答案 该 heapq.nsmallest() 函数将整齐,有效地做到这一点: 本质上是这样说的:“给我三个与 6.5 绝对差值最小的输入值”。 算

  • 我有一个包含一些整数值的数组,我需要得到其中的一个子集,它给我的最大和小于给定值 假设我有一个数组: 我想得到这个数组的一个子集,最大化总和,但低于用户给定的限制,比如250。在这种情况下,它应该返回[139,40,29]<我看了一下这个问题和相关的答案,并尝试使用给出的代码,但我不太理解。无论如何,我已经尝试过了,将最小值设置为0,将最大值设置为给定的限制,但它总是返回“5”,这是不正确的,因为