我想到了另一种基于@Harry He的想法的解决方案。可能不是最优雅的,但我理解如下:
我们以经典的简单示例PowerSet of S P(S) = {{1},{2},{3}}为例。我们知道获取子集数量的公式是2^n (7 + 空子集)。对于这个例子,2^3 = 8个子集。
为了找到每个子集,我们需要将0-7十进制转换为二进制表示,如下面的转换表所示:
如果我们按行遍历表格,每行将产生一个子集,并且每个子集的值将来自已启用位的值。
Bin Value部分中的每列对应于原始输入集中的索引位置。
以下是我的代码:
public class PowerSet {
public static void main(String[] args) {
PowerSet ps = new PowerSet();
Set<Integer> set = new HashSet<Integer>();
set.add(1);
set.add(2);
set.add(3);
for (Set<Integer> s : ps.powerSet(set)) {
System.out.println(s);
}
}
public Set<Set<Integer>> powerSet(Set<Integer> originalSet) {
int size = originalSet.size();
int numberOfSubSets = (int) Math.pow(2, size);
Set<Set<Integer>> sets = new HashSet<Set<Integer>>();
ArrayList<Integer> originalList = new ArrayList<Integer>(originalSet);
for (int i = 0; i < numberOfSubSets; i++) {
String bin = getPaddedBinString(i, size);
Set<Integer> set = getSet(bin, originalList));
sets.add(set);
}
return sets;
}
private Set<Integer> getSet(String bin, List<Integer> origValues){
Set<Integer> result = new HashSet<Integer>();
for(int i = bin.length()-1; i >= 0; i--){
if(bin.charAt(i) == '1'){
int val = origValues.get(i);
result.add(val);
}
}
return result;
}
private String getPaddedBinString(int i, int size) {
String bin = Integer.toBinaryString(i);
bin = String.format("%0" + size + "d", Integer.parseInt(bin));
return bin;
}
}