Hier sind zwei verschiedene Lösungen dazu. Für beide wurde die Eingabe erweitert, um zu zeigen, dass sie eine unterschiedliche Anzahl von Werten in jeder Unterliste verarbeiten kann.
Die erste Lösung berechnet die Gesamtzahl der Kombinationen und iteriert dann durch jede "nummerierte" Kombination und berechnet den zu verwendenden Wert aus jeder Unterliste. Diese Lösung sollte nur verwendet werden, wenn Unterlisten Array-basiert sind, da get(int index)
verwendet wird, da andernfalls die Leistung beeinträchtigt wird.
Die zweite Lösung wird so offen wie möglich gemacht, d. H. Die äußere "Liste" kann irgendeine Collection
sein, und "Unterlisten" können irgendeine Art von Iterable
sein. Es erzeugt ein bisschen mehr Müll, da es Iteratoren neu erstellen muss, aber das sollte kein Problem sein (GC ist in diesen Tagen gut).
Für die Variation erzeugen die beiden Lösungen die Kombinationen in einer anderen Reihenfolge, aber sie können beide geändert werden, um es anders zu machen.
Lösung 1
public static <T> List<List<T>> getCombinations(List<List<T>> valueSetList) {
int comboCount = 1;
for (List<T> valueSet : valueSetList)
comboCount = Math.multiplyExact(comboCount, valueSet.size()); // Fail if overflow
List<List<T>> combinations = new ArrayList<>(comboCount);
for (int comboNumber = 0; comboNumber < comboCount; comboNumber++) {
List<T> combination = new ArrayList<>(valueSetList.size());
int remain = comboNumber;
for (List<T> valueSet : valueSetList) {
combination.add(valueSet.get(remain % valueSet.size()));
remain /= valueSet.size();
}
combinations.add(combination);
}
return combinations;
}
Lösung 2
@SuppressWarnings("unchecked")
public static <T> List<List<T>> getCombinations(Collection<? extends Iterable<T>> valueSetCollection) {
Iterable<T>[] valueSets = new Iterable[valueSetCollection.size()];
Iterator<T>[] valueIters = new Iterator[valueSetCollection.size()];
T[] values = (T[]) new Object[valueSetCollection.size()];
int i = 0;
for (Iterable<T> valueSet : valueSetCollection) {
valueSets[i] = valueSet; // Copy to array for fast index lookup
valueIters[i] = valueSet.iterator();
values[i] = valueIters[i].next(); // Fail if a wordSet is empty
i++;
}
List<List<T>> combinations = new ArrayList<>();
NEXT_COMBO: for (;;) {
combinations.add(Arrays.asList(values.clone()));
for (i = values.length - 1; i >= 0; i--) {
if (valueIters[i].hasNext()) {
values[i] = valueIters[i].next();
continue NEXT_COMBO;
}
valueIters[i] = valueSets[i].iterator();
values[i] = valueIters[i].next();
}
return combinations;
}
}
-Test
getCombinations(Arrays.asList(
Arrays.asList("quick","lazy"),
Arrays.asList("brown","grey","black","red"),
Arrays.asList("fox","dog","wolf")
)).forEach(System.out::println);
Ausgabe 1
[quick, brown, fox]
[lazy, brown, fox]
[quick, grey, fox]
[lazy, grey, fox]
[quick, black, fox]
[lazy, black, fox]
[quick, red, fox]
[lazy, red, fox]
[quick, brown, dog]
[lazy, brown, dog]
[quick, grey, dog]
[lazy, grey, dog]
[quick, black, dog]
[lazy, black, dog]
[quick, red, dog]
[lazy, red, dog]
[quick, brown, wolf]
[lazy, brown, wolf]
[quick, grey, wolf]
[lazy, grey, wolf]
[quick, black, wolf]
[lazy, black, wolf]
[quick, red, wolf]
[lazy, red, wolf]
Ausgang 2
[quick, brown, fox]
[quick, brown, dog]
[quick, brown, wolf]
[quick, grey, fox]
[quick, grey, dog]
[quick, grey, wolf]
[quick, black, fox]
[quick, black, dog]
[quick, black, wolf]
[quick, red, fox]
[quick, red, dog]
[quick, red, wolf]
[lazy, brown, fox]
[lazy, brown, dog]
[lazy, brown, wolf]
[lazy, grey, fox]
[lazy, grey, dog]
[lazy, grey, wolf]
[lazy, black, fox]
[lazy, black, dog]
[lazy, black, wolf]
[lazy, red, fox]
[lazy, red, dog]
[lazy, red, wolf]
Können Sie die erwartete Ausgabe auflisten. Das wäre hilfreich. – anon
Wir wollen keine Fragen direkt von deinen Hausaufgaben sehen, wir haben bereits unsere Gebühren bezahlt. Mit welchem Teil kämpfst du? Hast du irgendwas probiert? –
@ J.Knight Ich möchte die Zeit Komplexität ohne Rekursion verbessern. Ist das möglich? – sach20