Вы можете сделать это с помощью следующего рекурсивного метода:
public static<T> ArrayList<ArrayList<T>> getPermutations (List<T> elements, int k) {
return getPermutations (elements,k,0);
}
public static<T> ArrayList<ArrayList<T>> getPermutations (List<T> elements, int k, int i) {
ArrayList<ArrayList<T>> results = new ArrayList<>();
if(k > 0) {
int n = elements.size();
for(int j = i; j <= n-k; j++) {
T val = elements.get(j);
ArrayList<ArrayList<T>> tails = getPermutations(elements,k-1,j+1);
for(ArrayList<T> tail : tails) {
ArrayList<T> result = new ArrayList<>();
result.add(val);
result.addAll(tail);
results.add(result);
}
}
} else {
results.add(new ArrayList<T>());
}
return results;
}
You может затем запустить его, например, с помощью (jDoodle):
который генерирует:
[a, b]
[a, c]
[b, c]
----------
[a, b, c]
----------
[a, b]
[a, c]
[a, d]
[b, c]
[b, d]
[c, d]
----------
[a, b, c]
[a, b, d]
[a, c, d]
[b, c, d]
Программа работает следующим образом: k
это число элементов, которые мы еще должны выбрать, и i
текущее значение смещения. Первоначально это значение смещения равно 0
.
Теперь мы итерации от i
до n-k
, ища потенциальных кандидатов, чтобы быть частью головы. Каждый элемент в этом диапазоне будет головкой для некоторых комбинаций. Мы выполняем рекурсию в остальной части списка. Рекурсия генерирует все списки, которые принимают k-1 элементов в остальной части списка. Тогда наша задача - просто добавить голову вперед и вернуть список.
Вы можете реализовать это как более оперативно, так и более консервативно, используя специальную форму LinkedList
s (которые являются общими для логических и функциональных языков программирования).
'n' является частью ввода также? Итак, для 'n = 3' вы хотите сгенерировать все комбинации с тремя элементами? –
Да, n - входной параметр. Может быть, k подойдет лучше. Из набора с n элементами я хочу все комбинации с k элементами. Должны быть комбинации «n выбрать k». – MWin123
Это можно решить с помощью [комбинаторной системы номеров] (http://stackoverflow.com/a/37736843/1090562) –