思路:对于一个集合的元素来说,它要么在这个子集里面(1),要么不在子集(0),就像下面这样 {1,2},它的所有子集有 {},{1},{2},{1,2},翻译成在与不在的意思就是:对于空集,一个元素都没有,就是 00 ,只有2,就是 01,只有1就是 10,有1有2 ,就是 11,所以,要是能够将集合变成数组,然后和相应 1、0组成数组一一对应成哪儿有1,那个就放在一个子集里面,非常奇妙的解法!
import java.util.Set;
import java.util.TreeSet;
import java.util.HashSet;
import java.util.List;
import java.util.ArrayList;
public class SubSet{
public void init(int n){
for (int i=0;i<n ;i++ ) {
strSet.add(String.valueOf(i));
}
}
Set<String> strSet=new TreeSet<String>();
Set<Set<String>> subSet=new HashSet<Set<String>>();
public static void main(String[] args) {
SubSet ss=new SubSet();
ss.init(3);
// ss.getSubSet();
ss.getSubSet2(ss.strSet);
ss.myprint(ss.subSet);
}
public void myprint(Set<Set<String>> subSet){
for (Set<String> s:subSet ) {
System.out.println(s);
}
}
//解法2
public void getSubSet2(Set<String> strSet){
int total=strSet.size();
Object[] str=strSet.toArray();
//左移的性质,恰好是2的N次方
for (int i=0;i<(1<<total) ; i++) {
Set<String> temp=new TreeSet<String>();
for (int j=0;j<total ;j++ ) {
//需要遍历整个组的下标,因此每次都需要将1左移j位
//而按位与运算则会只输出都是1
//在这里 i是说我要那几位数,这几位数是一个子集,然后j就遍历整个数组,找到这几位
if ((i & (1<<j))!=0) {
temp.add(str[j].toString());
}
}
subSet.add(temp);
}
}
//解法1
public void getSubSet(){
int total=strSet.size();
Object[] str=strSet.toArray();
//数学知识,一个集合的所有子集的个数是2的N次方,N是集合元素的个数
for (int i=0;i<Math.pow(2,total);i++ ) {
String str1=Integer.toBinaryString(i);
//java里面的Integer.toBinaryString()会把二进制前的0给去掉,为了一一对应,当然的补起来
while(str1.length()<total){
str1="0"+str1;
}
char[]ch=str1.toCharArray();
Set<String> temp=new TreeSet<String>();
for(int j=0;j<ch.length;j++){
if (ch[j]=='1') {
temp.add(str[j].toString());
}
}
subSet.add(temp);
}
}
}