子集
假设**非空集合A中含有n个元素,则有:
- A的子集个数为2^n。
- A的真子集的个数为2^n - 1。
- A的非空子集的个数为2^n - 1
- A的非空真子集的个数为2^n - 2。
递归
//递归
public Set<Set<Integer>> getSubsetsRecurse(int []set ,int length,int cur){
Set<Set<Integer>> finallySet = new HashSet<>();//最终那个大集合
//递归出口
if(cur == 0){
//空集
Set<Integer> nil = new HashSet<>();
//一个元素
Set<Integer> first = new HashSet<>();
first.add(set[0]);
finallySet.add(nil);
finallySet.add(first);
return finallySet;
}
//递归得到前n-1个元素的子集
Set<Set<Integer>> oldSet = getSubsetsRecurse(set,length,cur-1);
finallySet.addAll(oldSet);
for (Set<Integer> oldSetElement:oldSet){
//防止浅拷贝
Set<Integer> clone = (Set<Integer>) ((HashSet) oldSetElement).clone();
clone.add(set[cur]);
finallySet.add(clone);
}
return finallySet;
}
迭代
注意迭代器修改集合问题
//
public Set<Set<Integer>> getSubsets(int []set ,int length,int cur){
Set<Set<Integer>> finallySet = new HashSet<>();
finallySet.add(new HashSet<>());
for (int i = 0; i < length; i++) {
//
Set<Set<Integer>> tempSet = new HashSet<>();
tempSet.addAll(finallySet);
for (Set<Integer> s : finallySet) {
//deep copy
Set<Integer> clone = (Set<Integer>) ((HashSet) s).clone();
clone.add(set[i]);
tempSet.add(clone);
}
//finallySet.addAll(tempSet);
finallySet = tempSet;//fast
}
return finallySet;
}
二进制解法
此种方法可以按字典序输出
//binary利用二进制
public Set<Set<Integer>> getSubsets(Integer []set ,int length) {
Arrays.sort(set,new Comparator<Integer>(){
@Override
public int compare(Integer o1, Integer o2) {
return (o2-o1);//从大到小 快排 如果是o1-o2从小到大
}
});
Set<Set<Integer>> finallySet = new HashSet<>();//非空子集
for (int i = ((1<<length)-1);i>0;--i){
Set<Integer> subSet = new HashSet<>();//每一个二进制数对应一个集合
for(int j = length - 1;j >= 0; --j ){
if(((i>>j)&1) == 1){
subSet.add(set[j]);
}
}
finallySet.add(subSet);
}
return finallySet;
}
测试
[[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]
[[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]
[[1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]