【问题标题】:Efficient algorithm for finding the intersection of repeated subdivisions of a list of elements查找元素列表的重复细分的交集的高效算法
【发布时间】:2020-11-05 16:34:26
【问题描述】:

为清晰起见编辑:我正在寻找 C# 中最有效(最好是优雅)的方法来查找同一集合的各个细分的 n 向交集。详情如下。


  1. 我有一个元素列表。为简单起见,假设它是整数 1-100。
  2. 此列表已分为多个组,因此所有元素都存在于一个组中。例如。 第 1 区
    • 第 1 组: 1,5-8,52-73
    • 第 2 组: 2-4,38-51
    • 第 3 组: 9-37,84-100
    • 第 4 组: 74-83
  3. 步骤 #2 已重复多次(即此列表有许多不同的部分)。例如。 第 2 区
    • 第 1 组: 1-27,59-80,99-100
    • 第 2 组: 28-31,81-98
    • 第 3 组: 32-58​​li>
  4. 我想“合并”(这可能是一个更好的术语)这些划分,这样如果任何两个元素在任何划分中是分开的,它们在最终结果中就会分开。换个说法:只有那些在所有部门中都在一起的元素才会在最终结果中一起出现。例如。对于上述两个部门(D =部门,G =组)
    • 第 1 组 (D1G1 x D2G2):1,5-8,59-73
    • 第 2 组 (D1G1 x D2G3):52-58​​li>
    • 第 3 组 (D1G2 x D2G1):2-4
    • 第 4 组 (D1G2 x D2G3):38-51
    • 第 5 组 (D1G3 x D2G1):9-27,99-100
    • 第 6 组 (D1G3 x D2G2):28-31,84-98
    • 第 7 组 (D1G3 x D2G3):32-37
    • 第 8 组 (D1G4 x D2G1):74-80
    • 第 9 组 (D1G4 x D2G2):81-83

我不关心最终结果中组的顺序。我只是在寻找最有效和最干净的解决方案。

目前我能想到的唯一方法是:

public IEnumerable<IEnumerable<int>> MergeDivisions(IEnumerable<IEnumerable<IEnumerable<int>>> divisions)
{
    var currentMerge = divisions.First();
    foreach (var division in divisions.Skip(1))
    {
        var nextMerge = new List<List<int>>();
        foreach (var currentMergeGroup in currentMerge)
        {
            foreach (var group in division)
            {
                var nextMergeGroup = currentMergeGroup.Intersect(group);
                if (nextMergeGroup.Any())
                    nextMerge.Add(nextMergeGroup.ToList());
            }
        }
        currentMerge = nextMerge;
    }
    return currentMerge;
}

【问题讨论】:

  • 我不太了解您的需求,但是通过查看您的代码,您似乎有某种树,也许您可​​以使用树结构并遍历它并采取相应的行动,即每个节点都可以专门化。

标签: c# algorithm optimization set


【解决方案1】:

提示:

如果我是对的,您只是想产生组的成对交集**,其中组可以描述为间隔列表[b,e)*。我假设间隔是从左到右排序的。由于所有区间都由两个边界描述,因此您可以使用平面列表。

例如

{1, 2, 5, 9, 52, 74} ∩ {28, 32, 71, 99}

现在想象一个标准的列表合并过程(如在 Mergesort 中),这将导致

{1, 2, 5, 9, 28, 32, 52, 71, 74, 99}

对于此列表中的每个边界,您可以准确判断哪些区间包含它以及以下元素。

{1, 2, 5, 9, 28, 32, 52, 71, 74, 99}
 1  -  1  -  1   -   1   3   2   -

3 表示1+2)。

现在很容易看出两组中的元素都是[71, 74),而只有第一组的元素是[1, 2)[5, 9)[28, 32)[52, 71)

*使用最后一个索引加一更方便。

**我不确定我是否理解您如何定义合并,但我想上述技术可能很有用。

【讨论】:

  • (1/2) 感谢您的回复。是的,你是对的,我正在寻找组的交集,但不是“成对”本身,而是更n-wise。例如,如果我有一组整数 [1,10] 并且它已被细分为 3 次组:D1G1: [1,5], D1G2: [6,10] D2G1: [1,3], D2G2: [4,10] D3G1: [1,7], D3G2: [8,10]
  • (2/2) 我正在寻找一种高效(快速)的方式来处理D1G1 ∩ D2G1 ∩ D3G1, D1G1 ∩ D2G1 ∩ D3G2, ... , D1G2 ∩ D2G2 ∩ D3G2。或更广义的D1 G1 ∩ ... ∩ Dm G1, ... , D1 Gn_1 ∩ ... ∩ Dm Gn_m。以上将导致:D1G1 ∩ D2G1 ∩ D3G1: [1,3] D1G1 ∩ D2G1 ∩ D3G2: D1G1 ∩ D2G2 ∩ D3G1: [4,5] D1G1 ∩ D2G2 ∩ D3G2: D1G2 ∩ D2G1 ∩ D3G1: D1G2 ∩ D2G1 ∩ D3G2: D1G2 ∩ D2G2 ∩ D3G1: [6,7] D1G2 ∩ D2G2 ∩ D3G2: [8,10]
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-29
  • 2010-12-06
  • 2014-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多