自上而下范围合并?

时间:2012-02-24 20:29:01

标签: algorithm merge range

我想合并一些这样的间隔:

>>> ranges = [(30, 45), (40, 50), (10, 50), (60, 90), (90, 100)]
>>> merge(ranges)
[(10, 50), (60, 100)]

我不在cs领域。我知道如何通过迭代来做到这一点,但想知道是否有一种更有效的“自上而下”的方法来更有效地合并它们,可能使用一些特殊的数据结构?

感谢。

3 个答案:

答案 0 :(得分:3)

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

如果你有所有的时间间隔,你可以做一些更简单的事情:

  1. 从输入

    开始

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

  2. 将范围列表转换为端点列表。如果你有范围(A,B),你将它转换为两个端点:(A,0)将是左端点,(B,1)将是正确的端点。

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

  3. 对端点进行排序

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

  4. 通过端点列表向前扫描。当您看到左端点时递增计数器,并在看到正确的端点时递减计数器。只要计数器达到0,就会关闭当前的合并间隔。

  5. 此解决方案可以在几行中实现。

答案 1 :(得分:2)

是的,有效的方法是使用interval tree

答案 2 :(得分: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;
}