题目
原文:
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); } } }