[英]Get all subsets of a set
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));
}
}
The result should be [[],[1],[2],[1,2]]
结果应该是
[[],[1],[2],[1,2]]
But I can't get the result, the exception is as follows: 但我无法得到结果,例外情况如下:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
Your while loop is incorrect. 你的while循环不正确。
Made slightly more succinct with a for-loop: 使用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));
}
}
Bear in mind that the subset operation is exponential, so you'll get a very large number of elements. 请记住,子集操作是指数级的,因此您将获得大量元素。 The implementation above will only work with about 32 input elements, as that yields 2^32 output subsets, which will very easily run you over the limit of an array...
上面的实现只适用于大约32个输入元素,因为它产生2 ^ 32个输出子集,这将非常容易地超过数组的限制...
Your problem appears to be in your loop. 你的问题似乎在你的循环中。 If you look at it:
如果你看一下:
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);
}
You'll notice that the outside for-loop is trying to count i
upwards from zero, and the inner while loop counts it back to zero every iteration, so the outer loop runs forever. 你会注意到外部for循环试图从零向上计数
i
,而内部while循环在每次迭代时将其计数回零,因此外循环永远运行。
Program runs forever. 程序永远运行。 Below statement execute continuesly and getting outOfMemory.
下面的语句继续执行并获取outOfMemory。 Variable i value is never bigger than max value, check it.
变量i值永远不会大于最大值,请检查它。
`subset.add(set.get(index));`
In a nutshell, your inner while-loop is changing the outer for-loop's loop variable ( i
). 简而言之,你的内部while循环正在改变外部for循环的循环变量(
i
)。 This is disrupting the outer loop iteration. 这会破坏外循环迭代。 At the end of the inner loop the value of
i
is going to be zero ... which means that the outer loop will never terminate. 在内循环结束时,
i
的值将为零...这意味着外循环永远不会终止。
Given what you are doing, the fix is to use a different variable (say j
) for the inner loop, and initialize it from i
. 鉴于你正在做什么,修复是为内循环使用不同的变量(比如
j
),并从i
初始化它。
This illustrates why it is a bad idea to change a for-loop variable inside the loop. 这说明了为什么在循环中更改for循环变量是个坏主意。
how about a recursive solution? 递归解决方案怎么样?
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;
}
}
Here is a Java 8 solution for this question: 以下是针对此问题的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;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.