在数组中查找长度为k的所有子集

h4c*_*k3d 30 arrays algorithm permutation set

给定一组{1,2,3,4,5...n}n个元素,我们需要找到长度为k的所有子集.

例如,如果n = 4且k = 2,output将是{1, 2}, {1, 3}, {1, 4}, {2, 3}, {2, 4}, {3, 4}.

我甚至无法弄清楚如何开始.我们不必使用内置的库函数,如next_permutation等.

需要C/C++或Java中的算法和实现.

ami*_*mit 43

递归是你完成这项任务的朋友.

对于每个元素 - 如果它在当前子集中则"猜测",并使用猜测递归调用,并且可以选择较小的超集.对"是"和"否"猜测都这样做 - 将导致所有可能的子集.
在一个停止条款中可以轻松地将自己限制在一定长度.

Java代码:

private static void getSubsets(List<Integer> superSet, int k, int idx, Set<Integer> current,List<Set<Integer>> solution) {
    //successful stop clause
    if (current.size() == k) {
        solution.add(new HashSet<>(current));
        return;
    }
    //unseccessful stop clause
    if (idx == superSet.size()) return;
    Integer x = superSet.get(idx);
    current.add(x);
    //"guess" x is in the subset
    getSubsets(superSet, k, idx+1, current, solution);
    current.remove(x);
    //"guess" x is not in the subset
    getSubsets(superSet, k, idx+1, current, solution);
}

public static List<Set<Integer>> getSubsets(List<Integer> superSet, int k) {
    List<Set<Integer>> res = new ArrayList<>();
    getSubsets(superSet, k, 0, new HashSet<Integer>(), res);
    return res;
}
Run Code Online (Sandbox Code Playgroud)

调用:

List<Integer> superSet = new ArrayList<>();
superSet.add(1);
superSet.add(2);
superSet.add(3);
superSet.add(4);
System.out.println(getSubsets(superSet,2));
Run Code Online (Sandbox Code Playgroud)

将产量:

[[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]]
Run Code Online (Sandbox Code Playgroud)

  • @sTEAK。:子集的数量是指数级的,所以我担心高效并不是真正的选择。祝你好运! (2认同)
  • @AdarHefer不,它是k的指数,它是输入 - 不是常数.所以n ^ k绝对不是多项式. (2认同)