列表列表的组合,使每个组合都有唯一的元素
Posted
技术标签:
【中文标题】列表列表的组合,使每个组合都有唯一的元素【英文标题】:Combination of a list of lists so that each combination has unique elements 【发布时间】:2018-11-11 05:10:42 【问题描述】:好吧,我有一个列表列表,就像标题所说的那样,我想组合 k 个列表,其中每个列表都有不同的元素。
示例:
我有以下列表:
1,2,3 , 1,11 , 2,3,6 , 6,5,7 , 4,8,9
这些列表的有效 3 尺寸组合可以是:
1,11, 4,8,9 ,6,5,7
这只是其中一个有效组合,我要返回的是 K 个列表的所有有效组合的列表。
无效的组合是:
1,11 ,2, 3, 6, 6, 5, 7
因为元素 6 出现在第二个和第三个列表中。
我已经有一个执行此操作的代码,但它只是查找所有可能的组合并在将其添加到最终结果列表之前检查它们是否有效。由于当 K 变大时,这个列表非常大(153 个列表),所以所花费的时间也非常大(在 K = 5 时,我需要大约 10 分钟。)
我想看看是否有有效的方法来做到这一点。 以下是我当前的代码(我要组合的列表是类 Item 的属性):
public void recursiveComb(List<Item> arr, int len, int startPosition, Item[] result)
if (len == 0)
if (valid(result.ToList()))
//Here I add the result to final list
//valid is just a function that checks if any list has repeated elements in other
return;
for (int i = startPosition; i <= arr.Count - len; i++)
result[result.Length - len] = arr[i];
recursiveComb(arr, len - 1, i + 1, result);
【问题讨论】:
我不明白这个问题...是的,我可以看到什么是有效的,什么是无效的,但是你想用这个做什么。过滤还是验证? 我想过滤所有有效的组合并将它们添加到最终列表中。 你关心哪些内部列表会被删除吗? 我的意思是你为什么保留1,11
而不是1,2,3
,我真的很困惑。您需要添加更多信息
@TheGeneral 他想展示与有效示例相关的无效示例。它只是他想要收集到列表中并在最后输出给用户的众多列表中的一种可能性。确实很有趣的问题。
【参考方案1】:
使用哈希集 https://msdn.microsoft.com/en-us/library/bb359438(v=vs.110).aspx 在您从列表/元组的输入列表中的候选者构建输出时跟踪不同的元素
通过遍历输入的元组列表来累积非重叠元组的输出列表,并将每个元组评估为候选者,如下所示: 对于每个输入元组,将每个元组元素插入 HashSet。如果您尝试插入的元素已经在集合中,则元组未通过约束并应被跳过,否则元组元素都与输出中已经存在的元素不同。
hashset 对象有效地维护了您接受的元组列表中不同项目的注册表。
【讨论】:
【参考方案2】:如果我正确理解了您的代码,那么您将输入中的每个 list<int>
传递给 recursiveComb()
函数。看起来像这样
for(int i = 0; i < inputnestedList.Count; i++)
recursiveComb();
// Inside of recursiveComb() you are using one more for loop with recursion.
// This I observed from your first parameter i.e. List<int>
如果我错了,请纠正我
这导致时间复杂度超过 O(n^2)
这是我最简单的解决方案,有两个没有递归的for循环。
List<List<int>> x = new List<List<int>> new List<int>()1,2,3 , new List<int>()1,11 , new List<int>()2,3,6 , new List<int>()6,5,7 , new List<int>()4,8,9 ;
List<List<int>> result = new List<List<int>>();
var watch = Stopwatch.StartNew();
for (int i = 0; i < x.Count;i++)
int temp = 0;
for (int j = 0; j < x.Count; j++)
if (i != j && x[i].Intersect(x[j]).Any())
temp++;
// This condition decides, that elements of ith list are available in other lists
if (temp <= 1)
result.Add(x[i]);
watch.Stop();
var elapsedMs = watch.Elapsed.TotalMilliseconds;
Console.WriteLine(elapsedMs);
现在当我打印执行时间时输出是
Execution Time: 11.4628
检查代码的执行时间。如果你的代码的执行时间比我的长,那么你可以认为它是高效的代码
代码证明:DotNetFiddler
愉快的编码
【讨论】:
您好,谢谢您的回答。问题是我想做不止一个 k 大小的组合。并将其添加到组合列表中。我想考虑所有可能和有效的组合并将它们添加到组合列表中。因此,例如在我原来的帖子中,输出应该是所有有效组合的列表,就像我给出的那样。 您是否从 dotnet fiddler 检查了我的实现,此处为 dotnetfiddle.net/7SJhGQ 此解决方案返回您的预期输出 是的,我做到了,问题是:这只是可能的组合之一,我想获得所有组合。【参考方案3】:如果我正确理解了您的问题,那么这将起作用:
/// <summary>
/// Get Unique List sets
/// </summary>
/// <param name="sets"></param>
/// <returns></returns>
public List<List<T>> GetUniqueSets<T>(List<List<T>> sets )
List<List<T>> cache = new List<List<T>>();
for (int i = 0; i < sets.Count; i++)
// add to cache if it's empty
if (cache.Count == 0)
cache.Add(sets[i]);
continue;
else
//check whether current item is in the cache and also whether current item intersects with any of the items in cache
var cacheItems = from item in cache where (item != sets[i] && item.Intersect(sets[i]).Count() == 0) select item;
//if not add to cache
if (cacheItems.Count() == cache.Count)
cache.Add(sets[i]);
return cache;
经过测试,速度很快,查找集合耗时 00:00:00.0186033。
【讨论】:
以上是关于列表列表的组合,使每个组合都有唯一的元素的主要内容,如果未能解决你的问题,请参考以下文章