递归之非空子集

/**
 请编写一个方法,返回某集合的所有非空子集。

 给定一个int数组A和数组的大小int n,请返回A的所有非空子集。
 保证A的元素个数小于等于20,且元素互异。

 各子集内部从大到小排序,子集之间字典逆序排序
 */

public class _非空子集 {
	  public static void main(String[] args) {
		    int[] A = {1, 2, 3};
		    _非空子集 obj = new _非空子集();


		    Set<Set<Integer>> subsets2 = obj.getSubsets2(A, A.length);
		    System.out.println(subsets2);

		    ArrayList<ArrayList<Integer>> subsets = obj.getSubsets(A, A.length);
		    System.out.println(subsets);
		  }

		  /**
		   * 二进制法,迭代法,或者逐步生成法
		   * @param A
		   * @param n
		   * @return
		   */
		  public ArrayList<ArrayList<Integer>> getSubsets(int[] A, int n) {
		    Arrays.sort(A);//正序排序
		    ArrayList<ArrayList<Integer>> res = new ArrayList<>();//大集合

		    for (int i = _快速幂.ex(2, n) - 1; i > 0; i--) {//大数字-1
		      ArrayList<Integer> s = new ArrayList<>();//对每个i建立一个集合
		      for (int j = n - 1; j >= 0; j--) {//检查哪个位上的二进制为1,从高位开始检查,高位对应着数组靠后的元素
		        if (((i >> j) & 1) == 1) {
		          s.add(A[j]);
		        }
		      }
		      res.add(s);
		    }
		    return res;
		  }

		  /*逐步生成迭代大法*/
		  public Set<Set<Integer>> getSubsets2(int[] A, int n) {
		    Set<Set<Integer>> res = new HashSet<>();
		    res.add(new HashSet<>());//初始化为空集
		    //从第一个元素开始处理
		    for (int i = 0; i < n; i++) {
		      Set<Set<Integer>> res_new = new HashSet<>();//新建一个大集合
		      res_new.addAll(res);//把原来集合中的每个子集都加入到新集合中
		      //遍历之前的集合,全部克隆一遍
		      for (Set e : res) {
		        Set clone = (Set) ((HashSet) e).clone();
		        clone.add(A[i]);//把当前元素加进去
		        res_new.add(clone);//把克隆的子集加到大集合中
		      }
		      res = res_new;
		    }
		    return res;
		  }

		  /**
		   * 增量构造法
		   * @param A
		   * @param n
		   * @return
		   */
		  public Set<Set<Integer>> getSubsets3(int[] A, int n) {
		    // Arrays.sort(A);
		    return getSubsets3Core(A, n, n - 1);

		  }

		  /**
		   * 递归增量构造法
		   * @param A
		   * @param n
		   * @param cur
		   * @return
		   */
		  private Set<Set<Integer>> getSubsets3Core(int[] A, int n, int cur) {
		    Set<Set<Integer>> newSet = new HashSet<>();
		    if (cur == 0) {//处理第一个元素
		      Set<Integer> nil = new HashSet<>();//空集
		      Set<Integer> first = new HashSet<>();//包含第一个元素的集合
		      first.add(A[0]);
		      newSet.add(nil);
		      newSet.add(first);
		      return newSet;
		    }

		    Set<Set<Integer>> oldSet = getSubsets3Core(A, n, cur - 1);
		    for (Set<Integer> set : oldSet) {
		      //对于每个子集,cur这个元素可以加进去,也可以不加进去
		      newSet.add(set);//保留原样
		      Set<Integer> clone = (Set<Integer>) ((HashSet) set).clone();
		      clone.add(A[cur]);//添加当前元素
		      newSet.add(clone);
		    }
		    return newSet;
		  }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值