[英]Is there a method returns all possible combinations for n choose k?
我正在尋找可從k集返回n個子集的任何組合的庫函數。 例如,我有一個{1,2,3,4,5}集合,並且需要此集合中包含的3個數字的任意組合。 順序無關緊要。 因此,此函數應返回:
[[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]]
我試圖自己寫它,但是沒有成功,我放棄了。 僅當我從任意集合中提取3個數字時,此方法才有效。 也許有人知道此問題的庫功能。
我根本不知道任何庫函數,但是您可以使用以下解決方案:
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);
}
}
這是使用流的簡單而簡短的解決方案:
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));
}
}
工作原理:方法subsets
產生給定大小的所有子集的集合。
如果size < 1
則返回一個集,其中僅包含空集。
否則,對於給定集合的每個元素,它將生成一個沒有此選定元素的新集合。 然后,它(遞歸地)生成size - 1
個子集中的子集。 然后將所選元素添加到結果中的每個集合中。 因此,結果中的所有集合都具有所需的大小。
遞歸終止,因為在每個遞歸級別中, size
將減小1,平均< 1
。
這里的假設是set.size() >= size
和size >= 0
。
我在這里找到了遞歸解決方案: https : //stackoverflow.com/a/16256122/10929764,但它只打印出組合。 我試圖對其進行修改,以將所有組合作為ArrayList返回,但是它不起作用。 這是代碼:
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;
}
它會正確打印所有組合:
[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]
但是當我打印出先前由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]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.