は、二つの異なるソリューションがありますこれに。どちらの場合も、入力は各サブリスト内のさまざまな値を処理できることを示すために拡張されています。
最初の解決策は、合計の組み合わせ数を計算し、各「番号付き」組み合わせを繰り返し、各サブリストから使用する値を計算します。このソリューションは、サブリストが配列ベースの場合にのみ使用してください。get(int index)
を使用しています。そうしないと、パフォーマンスが低下します。
第2の解決策は可能な限り開いている、すなわち外側の「リスト」は任意のCollection
とすることができ、「サブリスト」は任意の種類のIterable
とすることができる。それはイテレータを再作成し続ける必要があるので、もう少しゴミを生成しますが、それは問題ではありません(最近のGCは良いです)。
変更のために、2つのソリューションは異なる順序で組み合わせを生成しますが、どちらの方法でも変更することができます。
溶液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;
}
溶液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;
}
}
テスト
getCombinations(Arrays.asList(
Arrays.asList("quick","lazy"),
Arrays.asList("brown","grey","black","red"),
Arrays.asList("fox","dog","wolf")
)).forEach(System.out::println);
出力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]
出力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]
予想される出力をリストできますか。それは助けになるだろう。 – anon
私たちはあなたの宿題からまっすぐな質問は見たくありません。あなたはどんな部分に苦しんでいますか?何か試しましたか? –
@ J.Knight再帰を使わずに時間の複雑さを改善したいと思いますか? – sach20