简体   繁体   English

是否有一种方法会为n选择k返回所有可能的组合?

[英]Is there a method returns all possible combinations for n choose k?

I'm looking for library function which returns any combination of n subset from the k set. 我正在寻找可从k集返回n个子集的任何组合的库函数。 For example I have a set {1,2,3,4,5} and I need any combination of 3 numbers included in this set. 例如,我有一个{1,2,3,4,5}集合,并且需要此集合中包含的3个数字的任意组合。 Order doesn't matter. 顺序无关紧要。 So this function should returns: 因此,此函数应返回:

[[1, 2, 3], [1, 2, 4], [1, 2, 5], [1, 3, 4], [1, 3, 5], [1, 4, 5], [2, 3, 4], [2, 3, 5], [2, 4, 5], [3, 4, 5]] [[1、2、3],[1、2、4],[1、2、5],[1、3、4],[1、3、5],[1、4、5],[ 2,3,4],[2,3,5],[2,4,5],[3,4,5]]

I have tried to write it by myself, but unsuccesfully and I give up. 我试图自己写它,但是没有成功,我放弃了。 It works only when I take 3 numbers from any set. 仅当我从任意集合中提取3个数字时,此方法才有效。 Maybe someone knows library function for this issue. 也许有人知道此问题的库功能。

I do not know any library functions by heart but you could use the following solution: 我根本不知道任何库函数,但是您可以使用以下解决方案:

import java.io.PrintStream;
import java.util.*;

public class CombinationCalc<T> {
    private void getSubsets(List<T> input, int length, int index, Set<T> currentSet, List<Set<T>> solution) {
        if (currentSet.size() == length) {
            solution.add(new HashSet<>(currentSet));
            return;
        }
        if (index == input.size()) {
            return;
        }
        T x = input.get(index);
        currentSet.add(x);
        getSubsets(input, length, index + 1, currentSet, solution);
        currentSet.remove(x);
        getSubsets(input, length, index + 1, currentSet, solution);
    }

    public List<Set<T>> getSubsets(List<T> input, int length) {
        List<Set<T>> solution = new ArrayList<>();
        getSubsets(input, length, 0, new HashSet<>(), solution);
        return solution;
    }

    public void printSolution(List<Set<T>> solution, PrintStream ps) {
        Iterator<Set<T>> solutionIterator = solution.iterator();
        ps.print("[");
        if (!solutionIterator.hasNext()) {
            ps.print("]");
        }
        while (solutionIterator.hasNext()) {
            Set<T> solutionEntry = solutionIterator.next();
            Iterator<T> setEntry = solutionEntry.iterator();
            ps.print("[");
            if (!setEntry.hasNext()) {
                ps.print("]");
            }
            while (setEntry.hasNext()) {
                T entry = setEntry.next();
                ps.print(entry);
                if (setEntry.hasNext()) {
                    ps.print(", ");
                } else {
                    ps.print("]");
                }
            }
            if (solutionIterator.hasNext()) {
                ps.print(", ");
            } else {
                ps.print("]");
            }
        }
        ps.println();
    }


    public static void main(String[] args) {
        CombinationCalc<Integer> calc = new CombinationCalc<>();
        List<Integer> input = Arrays.asList(1, 2, 3, 4, 5);
        List<Set<Integer>> solution = calc.getSubsets(input, 3);

        calc.printSolution(solution, System.out);
    }
}

It's based on amit's solution . 它基于amit的 解决方案

This is a simple and short solution using streams: 这是使用流的简单而简短的解决方案:

import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;

import static java.util.stream.Collectors.toSet;

public class MakeSubsets {
  static <T> Set<Set<T>> subsets(Set<T> set, int size) {
    if (size < 1) {
      return Collections.singleton(Collections.emptySet());
    }
    return set.stream()
          .flatMap(e -> subsets(remove(set, e), size - 1).stream().map(s -> add(s, e)))
          .collect(toSet());
  }

  static <T> Set<T> add(Set<T> set, T elem) {
    Set<T> newSet = new LinkedHashSet<>(set);
    newSet.add(elem);
    return newSet;
  }

  static <T> Set<T> remove(Set<T> set, T elem) {
    Set<T> newSet = new LinkedHashSet<>(set);
    newSet.remove(elem);
    return newSet;
  }

  public static void main(String[] args) {
    Set<Integer> set = new LinkedHashSet<>(Arrays.asList(1, 2, 3, 4, 5));
    System.out.println(subsets(set, 3));
  }
}

How it works: The method subsets produces the set of all subsets of given size. 工作原理:方法subsets产生给定大小的所有子集的集合。

In case of size < 1 it returns a set, containing only the empty set. 如果size < 1则返回一个集,其中仅包含空集。

Otherwise for each element of the given set, it produces a new set without this selected element. 否则,对于给定集合的每个元素,它将生成一个没有此选定元素的新集合。 Then it produces (recursively) the set of the subsets with size - 1 elements of this smaller set. 然后,它(递归地)生成size - 1个子集中的子集。 It then adds the selected element to each set in the result. 然后将所选元素添加到结果中的每个集合中。 Therefore all sets in the result have the desired size. 因此,结果中的所有集合都具有所需的大小。

The recursion terminates because in each recursion level the size will decrease by one, which will evenually be < 1 . 递归终止,因为在每个递归级别中, size将减小1,平均< 1

The assumption here is that set.size() >= size and size >= 0 . 这里的假设是set.size() >= sizesize >= 0

I found here recursive solution: https://stackoverflow.com/a/16256122/10929764 but it only prints out combinations. 我在这里找到了递归解决方案: https : //stackoverflow.com/a/16256122/10929764,但它只打印出组合。 I tried to modify it to return all combinations as an ArrayList, but it doesn't work. 我试图对其进行修改,以将所有组合作为ArrayList返回,但是它不起作用。 Here is code: 这是代码:

public ArrayList<String[]> comb2(ArrayList<String>arr, int len, int startPosition, String[] result, ArrayList<String[]> allResults){
    if (len == 0){
        System.out.println(Arrays.toString(result));
        allResults.add(result);
        return allResults;
    }
    for (int i = startPosition; i <= arr.size()-len; i++){
        result[result.length - len] = arr.get(i);
        comb2(arr, len-1, i+1, result,allResults);
    }
    return allResults;
}

It prints out properly all combinations: 它会正确打印所有组合:

[A, B, C] [A, B, D] [A, B, E] [A, C, D] [A, C, E] [A, D, E] [B, C, D] [B, C, E] [B, D, E] [C, D, E] [A,B,C] [A,B,D] [A,B,E] [A,C,D] [A,C,E] [A,D,E] [B,C,D] [ B,C,E] [B,D,E] [C,D,E]

but when I print out allResults which was previously returned by comb2 method than I get: 但是当我打印出先前由comb2方法返回的allResults时,我得到了:

[C, D, E] [C, D, E] [C, D, E] [C, D, E] [C, D, E] [C, D, E] [C, D, E] [C, D, E] [C, D, E] [C, D, E] [C,D,E] [C,D,E] [C,D,E] [C,D,E] [C,D,E] [C,D,E] [C,D,E] [ C,D,E] [C,D,E] [C,D,E]

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

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