子集和java的难度

时间:2015-01-19 02:04:08

标签: java algorithm

我对子集求和问题有困难。

首先,我试图找到匹配目标的子集总和。第一个原始集S是[3,4,6,2,15,7,5,1,11]。我从一个文件中读取并将价格存储在ArrayList中。然后我让用户输入金额,并将子集相加以匹配用户输入的金额,或者给出与输入金额匹配或接近的近似子集和。

输入25时算法错误。它给出[3,4,6,2,7,1],这是错误的。目标金额25有几个解决方案,并且是[4,6,15], [15,7,3], [3,4,6,7,5], [3,4,6,11,1], [3,2,15,5].

我试图找到总和为2的子集,如果可能的话,找到最佳解决方案。在我的原始列表中,由于有9个元素,因此有512个子集组合。我在代码中实现这个很困难。

代码:

class Subset{
    private ArrayList<Integer> subset;
    private Scanner scan;

    public Subset(String filename) {
        try {
            File file = new File(filename);
            Scanner scan = new Scanner(file);
            subset = new ArrayList<Integer>();

            while(scan.hasNext()) {
                String readLine = scan.nextLine();
                int num = Integer.parseInt(readLine.split(" ")[1]);
                subset.add(num);
            }
        } catch(FileNotFoundException ex) {
            System.out.println(ex.getMessage());
        } finally {
            scan.close();
        }
    }

    public ArrayList<Integer> getPrices() {
        return this.subset;
    }

    public ArrayList<Integer> findSubset(int target) {
        ArrayList<Integer> newList = new ArrayList<Integer>();
        int sum = 0;
        for (int i = 0; i < subset.size(); i++) {
            if (sum += subset.get(i) <= target) {
                newList.add(subset.get(i));
                sum += newList.get(i);
            }
        }
        return newList;
   }

   public static void main(String[] args) {
       final String FILENAME = "groceries.txt";
       Subset sub = new Subset(FILENAME);
       Scanner scan = new Scanner(System.in);

       ArrayList<Integer> price = sub.getPrices();
       System.out.println("Prices in the list: ");
       System.out.println(price);

       System.out.price("Enter an amount to give you a subset.. ");
       System.out.println("Enter price: ");
       int amount = scan.nextInt();

       ArrayList<Integer> list = sub.findSubset(amount);

       System.out.println("The subset list is: "+list);

       scan.close();
   }
}

我的groceries.txt文件是:

bread 3
garlic 4
coke 6
potato 2
candy 15
chicken 7 
banana 5
tomato 1
beef 11

2 个答案:

答案 0 :(得分:0)

您的算法是扫描列表,包括值,只要它们不会给您太大的金额。这是一个贪婪的&#34;算法,因为它假定看起来可能有效的东西,会起作用。但是你有一个存在的证据表明这种问题并不适用(在这种情况下,一旦你加入了2,你就会失败)。

正如您在描述中所说:有很多可能的组合,您的程序需要检查更多。例如,对于列表中的每个值,您可以尝试使用包含的那些元素构建列表中其余元素的子集,然后尝试不包含它的那些元素。这将允许您检查所有可能的子集。

答案 1 :(得分:0)

您的方法findSubset(int target)不正确。此方法实际上将值sum初始化为零,然后循环遍历subset中的每个元素,并将其添加到解决方案子集中,如果其值加sum小于或等于{{1} }}。此算法不考虑target中的所有子集(它实际上不会考虑subset的任何子集,只考虑整个subset。)。此外,此算法将返回subset中具有等于或小于 subset的累积和的元素。

解决此问题的明显方法是生成target的每个可能子集,然后遍历每个子集,对元素求和,并在总和等于subset时返回该子集。通过记忆子集和,可以使用动态编程来改进这种方法。

顺便说一下,您可能希望将设置结构命名为target而不是set,以避免混淆。 :)

希望这有帮助!