求集合的所有子集

思路:对于一个集合的元素来说,它要么在这个子集里面(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);
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值