好的,我有一个列表列表,比如标题说明,我想制作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存在于第二个和第三个列表中。
我已经有了一个执行此操作的代码,但它只是找到所有可能的组合,并在将它添加到最终结果列表之前检查它们是否有效。由于这个列表列表非常大(153个列表),当K变大时,所花费的时间也非常大(在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);
}
}
答案 0 :(得分:0)
使用HashSet https://msdn.microsoft.com/en-us/library/bb359438(v=vs.110).aspx 在列表/元组的输入列表中构建候选项的输出时跟踪不同的元素
通过迭代元组的输入列表来累积非重叠元组的输出列表,并将每个元组评估为候选元素,如下所示: 对于每个输入元组,将每个元组元素插入HashSet。如果您尝试插入的元素已经在集合中,则元组将失败约束并应跳过,否则元组元素将与输出中已有的元素不同。
hashset对象有效地维护了您接受的元组列表中不同项的注册表。
答案 1 :(得分:0)
如果我正确理解了您的代码,那么您将每个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)
这是我最简单的解决方案,有两个没有递归的forloops。
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
快乐编码
答案 2 :(得分:0)
如果我理解你的问题,那么这将有效:
/// <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之间进行了搜索。