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
答案 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;
}