簡體   English   中英

是否有一種方法會為n選擇k返回所有可能的組合?

[英]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);
    }
}

它基於amit的 解決方案

這是使用流的簡單而簡短的解決方案:

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() >= sizesize >= 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM