使用Java从每个列表中选择一个单词,而不使用递归,从列表中查找所有单词的组合
鉴于:使用Java从每个列表中选择一个单词,而不使用递归,从列表中查找所有单词的组合,java,Java,鉴于: [[“快”、“懒”]、[“棕色”、“灰色”]、[“狐狸”、“狗”] 使用Java从每个列表中只选择一个单词来查找所有组合 解决方案应适用于任何此类列表 可能的最佳时间复杂度 不使用递归 我的解决方案: public static <T> Set<List<T>> getCombinations(List<List<T>> lists) { Set<List<T>> combinations =
[[“快”、“懒”]、[“棕色”、“灰色”]、[“狐狸”、“狗”]
使用Java从每个列表中只选择一个单词来查找所有组合
- 解决方案应适用于任何此类列表
- 可能的最佳时间复杂度
- 不使用递归
public static <T> Set<List<T>> getCombinations(List<List<T>> lists) {
Set<List<T>> combinations = new HashSet<List<T>>();
Set<List<T>> newCombinations;
int index = 0;
// extract each of the integers in the first list
// and add each to ints as a new list
for(T i: lists.get(0)) {
List<T> newList = new ArrayList<T>();
newList.add(i);
combinations.add(newList);
}
index++;
while(index < lists.size()) {
List<T> nextList = lists.get(index);
newCombinations = new HashSet<List<T>>();
for(List<T> first: combinations) {
for(T second: nextList) {
List<T> newList = new ArrayList<T>();
newList.addAll(first);
newList.add(second);
newCombinations.add(newList);
}
}
combinations = newCombinations;
index++;
}
return combinations;
}
publicstaticset-getcombines(列表){
集合组合=新的HashSet();
设置新的二进制文件;
int指数=0;
//提取第一个列表中的每个整数
//并将其作为新列表添加到ints
for(ti:list.get(0)){
List newList=newarraylist();
新列表。添加(i);
组合。添加(新列表);
}
索引++;
while(索引
这里有两种不同的解决方案。对于这两种情况,输入都进行了扩展,以表明它可以处理每个子列表中不同数量的值
第一个解决方案计算组合的总数,然后迭代每个“编号”组合,从每个子列表中计算要使用的值。仅当子列表基于数组时才应使用此解决方案,因为它使用get(int index)
,否则性能将降低
第二种解决方案是尽可能开放的,即外部“列表”可以是任何集合
,“子列表”可以是任何类型的Iterable
。它会产生更多的垃圾,因为它必须不断地重新创建迭代器,但这不应该是一个问题(现在GC很好)
对于变化,这两种解决方案以不同的顺序生成组合,但它们都可以通过另一种方式进行更改
解决方案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;
}
输出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;
}
}
[快,布朗,福克斯]
[快,布朗,狗]
[快,布朗,狼]
[快,格雷,狐狸]
[快,格雷,狗]
[快,灰色,狼]
[快,黑,狐狸]
[快,黑,狗]
[快,黑,狼]
[快,瑞德,狐狸]
[快,瑞德,狗]
[快,红,狼]
[懒,棕色,狐狸]
[懒,棕色,狗]
[懒,布朗,狼]
[懒,灰,狐狸]
[懒,灰,狗]
[懒,灰,狼]
[懒,黑,狐狸]
[懒,黑,狗]
[懒,黑,狼]
[懒,红,狐狸]
[懒,红,狗]
[懒,红,狼]
试试这个
public static <T> Set<List<T>> getCombinations(List<List<T>> lists) {
int max = 1;
for (List<T> list : lists)
max *= list.size();
Set<List<T>> result = new HashSet<>(max);
for (int i = 0; i < max; ++i) {
List<T> newSublist = new ArrayList<>();
int n = i;
for (List<T> list : lists) {
int size = list.size();
newSublist.add(list.get(n % size));
n /= size;
}
result.add(newSublist);
}
return result;
}
publicstaticset-getcombines(列表){
int max=1;
用于(列表:列表)
max*=list.size();
设置结果=新哈希集(最大值);
对于(int i=0;i
您能列出预期的输出吗。那会很有帮助的。我们不想直接从你的作业中看到问题,我们已经完成了我们的任务。你在挣扎什么?你尝试过什么吗?@J.Knight我想在不使用递归的情况下提高时间复杂度。这可能吗?我不相信不使用递归这是可能的,但这应该可以简化,只需对内部和外部列表运行一个嵌套的for循环,然后每次将结果的组合添加到HashSet中,它将不允许任何重复。我可以问一下,当您实际处理字符串时,为什么您的解决方案是指整数吗?很好的工作伙伴:)@Andreas解决方案1的时间复杂度是O(n^2)。它比我的好吗?@sach20我不知道它是O(n^2),但我也不知道你对n
的定义是什么。溶液1的性能为O(nm),其中n
是组合数,m
是每个组合的值数。不可能小于此值,因为您必须为结果添加那么多值。您的解决方案的时间复杂度为O(n^2)。这比我的解决方案有改进吗?