假设我有一个字母列表:
String list[] = {"A","B","C","D","E","F","G","H","I","J"};
使用Java在列表中查找所有可能的4个组的最简单方法是什么(假设顺序不重要,这意味着ABCD与DCBA相同)?
我遇到了这个What's the quickest way to find all possible pairs in list?,我尝试通过这样做扩展解决方案:
for(int i=0;i<=list.length-4;i++){
for(int j=i+1;j<=list.length-3;j++){
for(int k=i+2;k<=list.length-2;k++){
for(int l=i+3;l<=list.length-1;l++){
System.out.println(list[i]+","+list[j]+","+list[k]+","+list[l]);
}
}
}
}
}
但很明显,这是不对的。如果有人可以帮助提供解决方案,这是上述链接的解决方案的扩展,那将是很好的。谢谢!
答案 0 :(得分:3)
我怀疑这是最快的,或者说无论如何都是最有效的,但我喜欢它(而且它更通用)。
这基本上是为了从n个元素的(排序)列表中获取大小为k的所有组合,依次取每个n-k + 1个第一个元素,并附加大小为k-1的所有组合。之后的清单。
要终止递归,如果k = 1,只需返回每个元素的单例列表列表。
为了使这个具体,在你的例子中,它确实:
“A”,包含来自“B”的3个字母的所有可能组合 - 附加“J”
与
一起“B”,包含来自“C” - “J”的3个字母的所有可能组合
与
一起“C”,包含来自“D” - “J”的3个字母的所有可能组合
...
“F”,包含来自“G” - “J”的3个字母的所有可能组合
与
一起“G”,包含“H”的3个字母的所有可能组合 - 附加“J”(只有1个)
要获得“B” - “J”中3个字母的所有可能组合,它确实
“B”,包含来自“C” - “J”的2个字母的所有可能组合
与
一起“C”,包含来自“D” - “J”的2个字母的所有可能组合
等
关于列表的初始排序,组合按字典顺序生成。
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class Combinatorics {
/**
* Computes all combinations of items of size <code>size</code>
* Assumes that items contains no replicates<
* @param items
* @param size
* @return A List of all possible Lists of items, each List of size <code>size</code>.
*/
public static <T extends Comparable<? super T>> List<List<T>> combinations(List<T> items, int size) {
if (size == 1) {
List<List<T>> result = new ArrayList<>();
for (T item : items) {
result.add(Collections.singletonList(item));
}
return result ;
}
List<List<T>> result = new ArrayList<>();
for (int i=0; i <= items.size() - size; i++) {
T firstItem = items.get(i);
List<List<T>> additionalItems = combinations(items.subList(i+1, items.size()), size-1) ;
for (List<T> additional : additionalItems) {
List<T> combination = new ArrayList<>();
combination.add(firstItem);
combination.addAll(additional);
result.add(combination);
}
}
return result ;
}
public static void main(String[] args) {
List<String> values = Arrays.asList("A", "C", "B", "D", "E", "F", "G", "H", "I", "J");
List<List<String>> allCombinations = combinations(values, 4);
for (List<String> combination : allCombinations) {
System.out.println(combination);
}
System.out.println(allCombinations.size() + " total combinations");
}
}
答案 1 :(得分:2)
你很接近试试这个。
for(int i=0;i<=list.length-4;i++){
for(int j=i+1;j<=list.length-3;j++){
for(int k=j+1;k<=list.length-2;k++){// change i+2 to j+1
for(int l=k+1;l<=list.length-1;l++){// change i+3 to k+1
System.out.println(list[i]+","+list[j]+","+list[k]+","+list[l]);
}
}
}
}
修改
i + x
初始化会导致问题,因为它们是静态偏移,并且可以防止索引冲突。即,当j增量j+1
将等于i+2
导致碰撞时。通过使偏移j+1
而不是i+2
,它成为相对于j防止碰撞的动态偏移。