1. 程式人生 > >生成非空集合--逐步生成結果_二進位制解法

生成非空集合--逐步生成結果_二進位制解法

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;
    }
}