集合的子集

题目描述

请编写一个方法,返回某集合的所有非空子集。
给定一个int数组A和数组的大小int n,请返回A的所有非空子集。保证A的元素个数小于等于20,且元素互异。各子集内部从大到小排序,子集之间字典逆序排序,见样例。

测试样例:

[123,456,789]

返回:{[789,456,123],[789,456],[789,123],[789],[456 123],[456],[123]}

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Scanner;

public class Subset {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Scanner scanner = new Scanner(System.in);
        while(scanner.hasNext()){
            int n = scanner.nextInt();
            int[] A = new int[n];
            for (int i = 0; i < n; i++) {
                A[i] = scanner.nextInt();
            }
            ArrayList<ArrayList<Integer>> subsets = getSubsets1(A, n);
            for(int i=0;i<subsets.size();i++){
                for(int j=0;j<subsets.get(i).size();j++){
                    System.out.print(subsets.get(i).get(j) + " ");
                }
                System.out.println();
            }
        }
    }

    // 方法1 占位法
    public static ArrayList<ArrayList<Integer>> getSubsets(int[] A, int n) {
        ArrayList<ArrayList<Integer>> subsets = new ArrayList<ArrayList<Integer>>();
        int size = 1 << n;// 子集的大小(算上了空集)
        for (int i = 0; i < size; i++) {
            ArrayList<Integer> subList = new ArrayList<Integer>();
            int k = i;
            int index = 0;
            while (k > 0) {
                if ((k & 1) == 1) {
                    subList.add(A[index]);
                }
                k >>= 1;
                index++;
            }
            Collections.reverse(subList);
            if (subList.size() > 0) {// 除去空集
                subsets.add(subList);
            }
        }
        Collections.reverse(subsets);
        return subsets;
    }

    // 方法2 举个例子一目了然
    // 比如 A={1,2,3};
    /*
     * 1.首先生成一个元素的子集sets(1)={{1}}。 
     * 2.加入元素2,则sets(2)由三部分组成:
     * (1)在sets(1)的所有子集前边插入当前元素A[1]=2,得{{2,1}}; 
     * (2)A[1]单独作为一个子集{2};
     * (3)sets(1)同时也应包含到sets(2)中,sets(2) = {{2,1},{2},{1}}。
     * 3.加入元素3,则sets(3)由三部分组成: 
     * (1)在sets(2)的所有子集前边插入当前元素A[2]=3,得{{3,2,1},{3,2},{3,1}}; 
     * (2)A[2]单独作为一个子集{3};
     * (3)sets(2)同时也应包含到sets(3)中,sets(3) = {{3,2,1},{3,2},{3,1},{3},{2,1},{2},{1}}。
     */
    public static ArrayList<ArrayList<Integer>> getSubsets1(int[] A, int n) {
        Arrays.sort(A);// 先从小到大排序
        ArrayList<ArrayList<Integer>> outSet = new ArrayList<ArrayList<Integer>>(); // 表示整体的大集合
        ArrayList<Integer> inSet; // 集合元素
        if (n == 1) { //递归终止条件
            inSet = new ArrayList<Integer>();
            inSet.add(A[0]);
            outSet.add(inSet);
            return outSet;
        }
        ArrayList<ArrayList<Integer>> temp = getSubsets1(A, n - 1); // 取得sets(n-1)集合
        for (int i = 0; i < temp.size(); i++) { // 在sets(n-1)的所有子集前边插入当前元素A[n-1]
            inSet = new ArrayList<Integer>();
            inSet.add(A[n - 1]);
            for (int j = 0; j < temp.get(i).size(); j++) {
                inSet.add(temp.get(i).get(j));
            }
            outSet.add(inSet);
        }
        inSet = new ArrayList<Integer>();
        inSet.add(A[n - 1]); // A[n-1]单独作为一个子集
        outSet.add(inSet);
        outSet.addAll(temp);// sets(n-1)同时也应包含到sets(n)中
        return outSet;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值