列表列表的组合使每个组合具有唯一元素

时间:2018-06-01 06:03:43

标签: c# list combinations

好的,我有一个列表列表,比如标题说明,我想制作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);
    }
}

3 个答案:

答案 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之间进行了搜索。