Algorithm 自上而下的范围合并?

Algorithm 自上而下的范围合并?,algorithm,merge,range,Algorithm,Merge,Range,我想合并一些间隔,如下所示: >>> ranges = [(30, 45), (40, 50), (10, 50), (60, 90), (90, 100)] >>> merge(ranges) [(10, 50), (60, 100)] 我不在cs领域。我知道如何通过迭代来实现,但我想知道是否有更高效的“自顶向下”方法来更高效地合并它们,也许是使用一些特殊的数据结构 谢谢。是的,有效的方法是使用。区间树肯定有效,但它比您需要的更复杂。间隔树是一个“在线”解

我想合并一些间隔,如下所示:

>>> ranges = [(30, 45), (40, 50), (10, 50), (60, 90), (90, 100)]
>>> merge(ranges)
[(10, 50), (60, 100)]
我不在cs领域。我知道如何通过迭代来实现,但我想知道是否有更高效的“自顶向下”方法来更高效地合并它们,也许是使用一些特殊的数据结构


谢谢。

是的,有效的方法是使用。

区间树肯定有效,但它比您需要的更复杂。间隔树是一个“在线”解决方案,因此它允许您添加一些间隔、查看联合、添加更多间隔、再次查看等

如果预先准备好所有的时间间隔,您可以做一些更简单的事情:

  • 从输入开始

    范围=[(30,45)、(40,50)、(10,50)]

  • 将范围列表转换为端点列表。如果有范围(A,B),则将其转换为两个端点:(A,0)将是左端点,(B,1)将是右端点

    终点=[(30,0)、(45,1)、(40,0)、(50,1)、(10,0)、(50,1)]

  • 对端点进行排序

    终点=[(10,0)、(30,0)、(40,0)、(45,1)、(50,1)、(50,1)]

  • 向前扫描端点列表。看到左端点时递增计数器,看到右端点时递减计数器。每当计数器达到0时,关闭当前合并间隔


  • 这个解决方案可以用几行代码来实现。

    下面的算法在C#中实现。它使用
    DateTime
    间隔范围,但您可以随意调整它。一旦集合按升序开始排序,如果下一个间隔的开始时间在上一个间隔的结束时间或之前,则它们会重叠,如果需要,可以向外延长结束时间。否则它们不会重叠,您会将之前的一个保存到结果中

    public static List<DateTimeRange> MergeTimeRanges(List<DateTimeRange> inputRanges)
    {
      List<DateTimeRange> mergedRanges = new List<DateTimeRange>();
    
      // Sort in ascending start order.
      inputRanges.Sort();
    
      DateTime currentStart = inputRanges[0].Start;
      DateTime currentEnd = inputRanges[0].End;
    
      for (int i = 1; i < inputRanges.Count; i++)
      {
        if (inputRanges[i].Start <= currentEnd)
        {
          if (inputRanges[i].End > currentEnd)
          {
            currentEnd = inputRanges[i].End; // Extend range.
          }
        }
        else
        {
          // Save current range to output.
          mergedRanges.Add(new DateTimeRange(currentStart, currentEnd));
    
          currentStart = inputRanges[i].Start;
          currentEnd = inputRanges[i].End;
        }
      }
    
      mergedRanges.Add(new DateTimeRange(currentStart, currentEnd));
    
      return mergedRanges;
    }
    
    公共静态列表合并时间范围(列表输入范围)
    {
    List mergedRanges=新列表();
    //按升序开始排序。
    inputRanges.Sort();
    DateTime currentStart=inputRanges[0]。开始;
    DateTime currentEnd=inputRanges[0]。结束;
    for(int i=1;i
    Hi Jason,我刚查了一下区间树,得到了基本的想法。但是我对如何使用它来合并区间感到困惑,你能给我一个缺少链接的简要描述吗?谢谢。我唯一能想到的就是构造区间树,然后对区间进行排序,并使用最左边的区间作为第一个查询,搜索该树并获取所有相交区间,然后合并这些区间,并迭代地进行合并,直到合并的范围不变;然后使用下一个正确的间隔开始第二轮扫描。这是扫描整棵树的所有重叠间隔“子树”的正确方法吗?如果有多个重叠间隔簇,这是否有效?我非常喜欢这个优雅的想法:)是的,不管有多少簇,它都有效。每次计数器达到零,您就到达了合并集群的末尾。下一个端点必须是左端点(否则您的数据会被弄乱),它将启动下一个合并的集群。我现在看到了,尽管我认为这应该具有与排序和成对合并方法类似的时间复杂性,对吗?对-您可以基于左端点对间隔进行排序,然后向前迭代,如果间隔重叠,则合并间隔。老实说,我没有想到这种方法:)