题目
原文:
Write a method that returns all subsets of a set.
译文:
写一个方法返回一个集合的所有子集合。
解答
对于一个集合,它的总共子集数为2^n(包括空集)。对于S(5)={1,2,3,4,5},则S(5)的子集数可以写为:5与S(4)的子集的组合+S(4)的子集,得递归算法如下:
public static LinkedList<LinkedList<Integer>> recursionSubSet(int[] set,int n,int index){
LinkedList<LinkedList<Integer>> subsets=new LinkedList<LinkedList<Integer>>();
if(index==n){ //judge the end
LinkedList<Integer> subset=new LinkedList<Integer>();
subsets.add(subset);
}else{
LinkedList<LinkedList<Integer>> part=recursionSubSet(set,n,index+1);
int v=set[index];
for(int i=0;i<part.size();i++){
LinkedList<Integer> subset=part.get(i);
subsets.add(subset);
LinkedList<Integer> newsubset = new LinkedList<Integer>();
for(Integer entry:subset){
newsubset.add(entry);
}
newsubset.add(v);
subsets.add(newsubset);
}
}
return subsets;
}
另外,对于一个集合的任意一个子集,可以看做这个集合本身的每个元素是否出现而形成的一个序列,又因为子集总数为2^n,所以可以通过二进制来做标记,如:集合(1,2,3),当集合被标记为(0,0,0)是,则为空集;子集(1,3),不是2没出现,二进制位0,1和3出现则为1;所以集合(1,2,3)的子集可以用二进制000~111,8(2^3)个二进制标记,遍历每个二进制的每位,判断是否出现,再添加进对应的子集即可,代码如下:
public static LinkedList<LinkedList<Integer>> binarySubSet(int[] set,int n){
LinkedList<LinkedList<Integer>> subsets=new LinkedList<LinkedList<Integer>>();
int max=1<<n; //the number of total subset
for(int i=0;i<max;++i){
LinkedList<Integer> subset=new LinkedList<Integer>();
int index=0;
int j=i;
while(j>0){
if((j&1)==1){ //judge the byte
subset.add(set[index]);
}
j>>=1;
++index;
}
subsets.add(subset);
}
return subsets;
}
完整代码如下:
import java.util.LinkedList;
import java.util.Iterator;
class Q8_3{
//recursion
//n is the length of the set, index act as marking, at the beginning of 0
public static LinkedList<LinkedList<Integer>> recursionSubSet(int[] set,int n,int index){
LinkedList<LinkedList<Integer>> subsets=new LinkedList<LinkedList<Integer>>();
if(index==n){ //judge the end
LinkedList<Integer> subset=new LinkedList<Integer>();
subsets.add(subset);
}else{
LinkedList<LinkedList<Integer>> part=recursionSubSet(set,n,index+1);
int v=set[index];
for(int i=0;i<part.size();i++){
LinkedList<Integer> subset=part.get(i);
subsets.add(subset);
LinkedList<Integer> newsubset = new LinkedList<Integer>();
for(Integer entry:subset){
newsubset.add(entry);
}
newsubset.add(v);
subsets.add(newsubset);
}
}
return subsets;
}
//binary
//n is the length of the set
public static LinkedList<LinkedList<Integer>> binarySubSet(int[] set,int n){
LinkedList<LinkedList<Integer>> subsets=new LinkedList<LinkedList<Integer>>();
int max=1<<n; //the number of total subset
for(int i=0;i<max;++i){
LinkedList<Integer> subset=new LinkedList<Integer>();
int index=0;
int j=i;
while(j>0){
if((j&1)==1){ //judge the byte
subset.add(set[index]);
}
j>>=1;
++index;
}
subsets.add(subset);
}
return subsets;
}
public static void main(String[] args){
int[] dataset={1,2,3,4};
Iterator<LinkedList<Integer>> it=recursionSubSet(dataset,dataset.length,0).iterator();
while(it.hasNext()){
LinkedList<Integer> set=it.next();
System.out.println(set);
}
System.out.println("");
Iterator<LinkedList<Integer>> it1=binarySubSet(dataset,dataset.length).iterator();
while(it1.hasNext()){
LinkedList<Integer> set=it1.next();
System.out.println(set);
}
}
}
---EOF---