获取集合的所有子集

时间:2013-01-08 22:13:51

标签: java arrays

import java.util.ArrayList;

public class Subset { //Generate all subsets by generating all binary numbers
    public static ArrayList<ArrayList<Integer>> getSubsets2(ArrayList<Integer> set) {

        ArrayList<ArrayList<Integer>> allsubsets =
            new ArrayList<ArrayList<Integer>>();
        int max = 1 << set.size();             //there are 2 power n 
        for (int i = 0; i < max; i++) {
            ArrayList<Integer> subset = new ArrayList<Integer>();

            int index = 0;
            while (i > 0) {
                if ((i & 1) > 0) {
                    subset.add(set.get(index)); //Add elements to a new ArrayList
                }
                i >>= 1;
                index++;
            }
            allsubsets.add(subset);
        }
        return allsubsets;
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        ArrayList<Integer> set = new ArrayList<Integer>(); //Create an ArrayList
        set.add(1);
        set.add(2);

        System.out.println(getSubsets2(set));
    }
}

结果应为[[],[1],[2],[1,2]]

但我无法得到结果,例外情况如下:

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

6 个答案:

答案 0 :(得分:7)

您的while循环不正确。

使用for循环稍微简洁一点:

import java.util.ArrayList;

public class Subset { //Generate all subsets by generating all binary numbers
    public static ArrayList<ArrayList<Integer>> getSubsets2(ArrayList<Integer> set) {

        ArrayList<ArrayList<Integer>> allsubsets =
        new ArrayList<ArrayList<Integer>>();
        int max = 1 << set.size();             //there are 2 power n different subsets

        for (int i = 0; i < max; i++) {
            ArrayList<Integer> subset = new ArrayList<Integer>();
            for (int j = 0; j < set.size(); j++) {
                if (((i >> j) & 1) == 1) {
                    subset.add(set.get(j));
                }
            }
            allsubsets.add(subset);
        }
        return allsubsets;
    }

    public static void main(String[] args) {
        ArrayList<Integer> set = new ArrayList<Integer>(); //Create an ArrayList
        set.add(1);
        set.add(2);

        System.out.println(getSubsets2(set));
    }
}

请记住,子集操作是指数级的,因此您将获得大量元素。上面的实现只适用于大约32个输入元素,因为它产生2 ^ 32个输出子集,这将非常容易地超过数组的限制...

答案 1 :(得分:2)

您的问题似乎出现在您的循环中。如果你看一下:

for (int i = 0; i < max; i++) {
    ArrayList<Integer> subset = new ArrayList<Integer>();
    int index = 0;
    while (i > 0) {
        if ((i & 1) > 0) {
            subset.add(set.get(index)); //Add elements to a new ArrayList
        }
        i >>= 1;
        index++;
    }
    allsubsets.add(subset);
}

你会注意到外部for循环试图从零开始向上计数i,并且内部while循环在每次迭代时将其计数回零,因此外循环将永远运行。

答案 2 :(得分:0)

程序永远运行。下面的语句继续执行并获取outOfMemory。变量i值永远不会大于最大值,请检查它。

`subset.add(set.get(index));` 

答案 3 :(得分:0)

简而言之,你的内部while循环正在改变外部for循环的循环变量(i)。这会破坏外循环迭代。在内循环结束时,i的值将为零...这意味着外循环永远不会终止。

鉴于您正在做什么,修复方法是为内部循环使用不同的变量(比如j),并从i初始化它。


这说明了为什么在循环中更改for循环变量是个坏主意。

答案 4 :(得分:0)

递归解决方案怎么样?

vector<vector<int> > getSubsets(vector<int> a){


//base case
    //if there is just one item then its subsets are that item and empty item
    //for example all subsets of {1} are {1}, {}

    if(a.size() == 1){
        vector<vector<int> > temp;
        temp.push_back(a);

        vector<int> b;
        temp.push_back(b);

        return temp;

    }
    else
    {


         //here is what i am doing

         // getSubsets({1, 2, 3})
         //without = getSubsets({1, 2})
         //without = {1}, {2}, {}, {1, 2}

         //with = {1, 3}, {2, 3}, {3}, {1, 2, 3}

         //total = {{1}, {2}, {}, {1, 2}, {1, 3}, {2, 3}, {3}, {1, 2, 3}}

         //return total

        int last = a[a.size() - 1];

        a.pop_back();

        vector<vector<int> > without = getSubsets(a);

        vector<vector<int> > with = without;

        for(int i=0;i<without.size();i++){

            with[i].push_back(last);

        }

        vector<vector<int> > total;

        for(int j=0;j<without.size();j++){
            total.push_back(without[j]);
        }

        for(int k=0;k<with.size();k++){
            total.push_back(with[k]);
        }


        return total;
    }


}

答案 5 :(得分:0)

以下是此问题的Java 8解决方案:

public Set<Set<Integer>> getSubsets(Set<Integer> set) {
    if (set.isEmpty()) {
       return Collections.singleton(Collections.emptySet());
    }

    Set<Set<Integer>> subSets = set.stream().map(item -> {
        Set<Integer> clone = new HashSet<>(set);
        clone.remove(item);
        return clone;
    }).map(group -> getSubsets(group))
            .reduce(new HashSet<>(), (x, y) -> {
                x.addAll(y);
                return x;
            });

    subSets.add(set);
    return subSets;
}