生成非空集合--逐步生成结果_二进制解法

1.问题描述:

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

2.我们除了可以使用递归和递推的方法,此外我们还有一种更有技巧性的方法,那就是二进制的解法

假如数组的长度为3,那么它的非空集合的个数就位0 ~ 2 ^ n  - 1, 而在这个区间的这些数字的二进制位上的数字我们可以技巧性的使用,那就是该位上为1,就选择某位上对应的数字

下面以{1, 2 ,3}为例:

1 1 1      3 2 1

1 1 0      3 2

1 0 1      3 1

1 0 0      3

0 1 1      2 1

0 1 0      2 

0 0 1      1 

上面是用得到的是字典序逆序排列之后得到的非空集合(需要从高位进行处理)

3.具体的代码如下:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;
public class Main {
    //二进制上的数字代表该为是选择还是不选
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int A[] = new int[n];
        for(int i = 0; i < n; i++){
            A[i] = sc.nextInt();
        }
        List<List<Integer>> list = solve(A, n);
        for(List<Integer> listOut : list){
            if(listOut.size() == 0){
                list.remove(listOut);
                break;
            }
        }
        System.out.println(list);
    }

    private static List<List<Integer>> solve(int[] A, int n){
        Arrays.sort(A);
        List<List<Integer>> list = new ArrayList<>();
        int nExp = (int) Math.pow(2, n);
        for(int i = nExp; i > 0; i--){
            List<Integer> listNew = new ArrayList<>();
            for(int j = n - 1; j >= 0; j--){
                //检查哪一位上的数字为1
                if(((i >> j) & 1) == 1){
                    listNew.add(A[j]);
                }
            }    
            list.add(listNew);
        }
        return list;
    }
}
 

猜你喜欢

转载自blog.csdn.net/qq_39445165/article/details/83145335