繁体   English   中英

如何从 ArrayList 中获取子集?

[英]How can I get the subset from an ArrayList?

我正在处理一个问题,要求我“编写一个方法,返回由整数 1 到 N 形成的集合的所有子集,其中 N 传递给方法。” 如果我将 N = 3 传递给该方法,我的 output 应该看起来像[[0], [1], [2], [3], [1, 2], [1, 3], [2, 3], [1, 2, 3]] 我当前的 output 是[[0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3]]. 有没有办法让我打印出所需的范围,比如为 ArrayList 做 Arrays.copyOfRange()? 或者是否有另一种方法可以获得我想要的 output 的子集?

import java.util.ArrayList;
import java.util.HashSet;

public class HW3 {

    public static void main(String[] args) {
        System.out.println(powerset(3));
    }

    public static ArrayList<HashSet<Integer>> powerset(int N) {
        ArrayList<HashSet<Integer>> arrayList = new ArrayList<HashSet<Integer>>();
        HashSet<Integer> arrayListNew = new HashSet<Integer>();
        for (int i = 0; i <= N; i++)
            arrayListNew.add(i);

        for (int i = 0; i < (int) Math.pow(2, N); i++)
            arrayList.add(arrayListNew);

        return arrayList;
    }
}

“我有没有办法打印出所需的范围,比如为 ArrayList 做 Arrays.copyOfRange()?”

是的,使用 sublist() 在这里阅读更多

但是,您的问题不需要它。 您正在寻找的算法应该看起来像这样

//1st for loop iterate through all the possible sizes for the hash set
for(){
   //2nd for loop generate all possible combinations given the size
   for(){
   }
}
//might need to add the [0] urself at the end

更合适的方法是回溯

public class BacktrackTest {

    public static void main(String[] args) {
        powerset(3);
    }

    public static void powerset(int num) {
        if (num >= 10 || num < 1) {
            throw new IllegalArgumentException();
        }
        int[] chs = new int[num];
        for (int i = 1; i <= num; i++) {
            chs[i - 1] = i;
        }
        List<List<Integer>> resultList = new ArrayList<>();
        backtrack(0, chs, new ArrayList<>(), resultList);
        Collections.sort(resultList, (a, b) -> {
           int len1 = a.size();
           int len2 = b.size();
           return len1 - len2;
        });
        System.out.println(resultList);
    }

    public static void backtrack(int index, int[] chs, List<Integer> tempList, List<List<Integer>> resultList) {
        for (int i = index; i < chs.length; i++) {
            tempList.add(chs[i]);
            //此处必须用new ArrayList<>(tempList)的方式实现
            //否则会导致结果不正常(Java中的引用导致的)
            resultList.add(new ArrayList<>(tempList));
            backtrack(i + 1, chs, tempList, resultList);
            tempList.remove(tempList.size() - 1);
        }
    }
}

Java 小提琴演示

Output 结果:

在此处输入图像描述

public class HW3 {
static void printSubsets(int set[]) {
    int n = set.length;
    for (int i = 0; i < (1 << n); i++) {
        System.out.print("{ ");
        for (int j = 0; j < n; j++)
            if ((i & (1 << j)) > 0)
                System.out.print(set[j] + " ");

        System.out.println("}");
    }
}

public static void main(String[] args) {
    int n = 3;
    int[] set = new int[n+1];
    for(int i = 0; i<=n; i++){
        set[i]=i;
    }
    printSubsets(set);
}}

任何给定集合的子集总数等于 2^(集合中的元素数)。 如果我们仔细观察,它只是从 0 到 7 的二进制数,如下所示:

000 001 010 011 100 101 110 111

从右开始,第 i 个 position 处的 1 表示该集合的第 i 个元素存在,而 0 表示该元素不存在。 因此,我们要做的只是生成从 0 到 2^n – 1 的二进制数,其中 n 是集合的长度或集合中元素的数量。

时间复杂度: O(n * (2^n)),因为外循环运行 O(2^n),内循环运行 O(n)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM