返回某集合的所有子集

题目:

  给定一个int数组A和数组的大小n,编写一个方法返回集合A的所有子集。注意集合里面的元素互异。

  解这道题的思想本质上就是元素选与不选的问题。由此大概有三种方法解这道题。

  递归法:如果只有一个元素,那么它的子集有两个,分别是本身和空集,然后在已经有一个元素的子集的基础上,第二个元素有两种选法,那就是加入到前面的子集里面或者不加入到前面的子集里面,也就是选与不选的问题。而前面的子集一共有两个,对每一个子集都有来自于下一个元素的加入和不加入两种选法。那么就可以得出两个元素的子集一共有四个。依次类推,就可以得出n的元素所有子集(这里n个元素的子集一共有2n个,非空子集一共有2n-1个。)。

  迭代法:思想和递归法基本一样,区别是代码的方式不一样,关于它们的区别前面博客里面写着的。

  二进制法:观察规律可以发现任何元素只有两种情况可以选择,于是我们就可以想到用二进制来代表选与不选的情况。"1"代表这个元素已经选择,而"0"代表这个元素没有选择。假如三个元素 A B C ,那么 101 就代表B没有选择,所以101代表的子集为AC。

代码:

  1 import java.util.ArrayList;
  2 import java.util.Arrays;
  3 import java.util.HashSet;
  4 import java.util.Set;
  5 
  6 public class 非空子集 {
  7 
  8     public static void main(String[] args) {
  9         int[] A = {1, 2, 3};
 10 
 11         ArrayList<ArrayList<Integer>> subsets = getSubsets(A, A.length);
 12         System.out.println(subsets);
 13         
 14         Set<Set<Integer>> subsets2 = getSubsets2(A, A.length);
 15         System.out.println(subsets2);
 16         
 17         Set<Set<Integer>> subsets3 = getSubsets3(A, A.length);
 18         System.out.println(subsets3);
 19 
 20 
 21     }
 22     
 23     /**
 24      * 二进制法,迭代法,或者逐步生成法,性能最高
 25      */
 26     public static ArrayList<ArrayList<Integer>> getSubsets(int []A,int n){
 27         Arrays.sort(A);  // 正序排序
 28         ArrayList<ArrayList<Integer>> res = new ArrayList<>();  //大集合
 29         for(int i = ex(2, n);i>0;i--){         //大数字-1
 30             ArrayList<Integer> s = new ArrayList<>();  //对每个i建立一个集合
 31             for(int j = n-1;j>=0;j--){    //检查哪个位上的二进制为1,从高位开始检查,高位对应着数组靠后的元素
 32                 if(((i>>j)&1)==1){
 33                     s.add(A[j]);
 34                 }
 35             }
 36             res.add(s);
 37         }
 38         // 生成的结果逆序排序,如果要生成正序排列,很难完成,只有数组反转实现。
 39         return res;
 40     }
 41     
 42     /**
 43      * 逐步生成迭代大法
 44      */
 45     public static Set<Set<Integer>> getSubsets2(int[]A,int n){
 46         Set<Set<Integer>> res = new HashSet<>();  //初始化为空集
 47         res.add(new HashSet<>());
 48         //从第一个元素开始处理
 49         for(int i=0;i<n;i++){
 50             Set<Set<Integer>> res_new = new HashSet<>(); //新建一个大集合
 51             res_new.addAll(res);  //把原来集合中的每个子集都加入到新集合中
 52             for(Set e:res){     //遍历之前的集合,全部克隆一遍
 53                 Set clone = (Set) ((HashSet) e).clone(); 
 54                 clone.add(A[i]);  //把当前元素加进去
 55                 res_new.add(clone); //把克隆的子集加到大集合中
 56             }
 57             res = res_new;
 58         }
 59         return res;
 60     }
 61     
 62     /**
 63      * 递归法  增量构造法
 64      */
 65     public static Set<Set<Integer>> getSubsets3(int[]A,int n){
 66         // Arrays.sort(A);
 67         return getSubsetsCore(A,n,n-1);
 68     }
 69     
 70     public static Set<Set<Integer>> getSubsetsCore(int[] A, int n, int cur) {
 71         Set<Set<Integer>> newSet = new HashSet<>();
 72         if (cur==0) {     //处理第一个元素
 73             Set<Integer> nil = new HashSet<>();        //空集
 74             Set<Integer> first = new HashSet<>();    //包含第一个元素的集合
 75             first.add(A[0]);
 76             newSet.add(nil);
 77             newSet.add(first);
 78             return newSet;
 79         }
 80         Set<Set<Integer>> oldSet = getSubsetsCore(A, n, cur-1);
 81         for(Set<Integer> set:oldSet){
 82             //对于每个子集,cur这个元素可以加进去,也可以不加进去
 83             newSet.add(set);  //保留原样 选择不加进去
 84             Set<Integer> clone = (Set<Integer>) ((HashSet) set).clone();
 85             clone.add(A[cur]);        //添加当前元素
 86             newSet.add(clone);
 87         }
 88         return newSet;
 89     }
 90 
 91     public static int ex(int a,int n){
 92         if(n==0)return 1;
 93         if(n==1)return a;
 94         int temp = a; // a的1次方
 95         int res = 1;
 96         int exponent = 1;
 97         while((exponent<<1)<n){
 98             temp = temp * temp;
 99             exponent = exponent << 1;
100         }
101         res *= ex(a,n-exponent);
102         return res * temp;
103     }
104 
105 }

结果:

  

  

猜你喜欢

转载自www.cnblogs.com/xiaoyh/p/10344523.html