【问题标题】:The fastest algorithm determine range overlap最快的算法确定范围重叠
【发布时间】:2011-09-11 03:26:19
【问题描述】:

我有两组范围,每个范围都是一对表示开始和结束的整数。确定两个范围之间是否有任何重叠的最快方法是什么?

谢谢。

【问题讨论】:

  • 范围本身是分离的?
  • 你是从外部来源获得的吗?或者您可以为这些范围集保留自己的数据库吗?
  • 你可以在这个链接中看到我的答案:stackoverflow.com/a/16961719/1534785

标签: c# .net algorithm overlap


【解决方案1】:

如果它们都按开始排序,您只需检查两个集合中的第一个范围,看看它们是否重叠,如果没有移动到集合中具有最小末端偏移的下一个项目,请冲洗并重复直到找到重叠或者你在一组的末尾。如果已经排序,则为 O(n),否则为 O(n log n)。

【讨论】:

    【解决方案2】:

    让,

    r1 = { s1, e1}
    r2 = { s2, e2}

    创建位向量

    最大 (e1, e2} - 最小 {s1, s2}
    (或者为了简单起见,假设它是从 0 到 max (e1, e2) )

    将每个范围设置为开始和结束之间的一组位,即

    e1mask = ((0x1<<(e1-s1))-1)<<s1;
    e2mask = ((0x1<<(e2-s2))-1)<<s2;
    

    如果

    ,这些范围重叠
    e1mask & e2mask != 0
    

    【讨论】:

      【解决方案3】:

      我会编写以下算法:

      bool Overlap(int s, int e, int s1, int e1) 
      {
        if(s > s1 && s < e1)
           return true;
        if(s1 > s && s1 < e)
           return true;
        return false;
      }
      int[] overlaps(Range[] ranges)
      {
         List<int> res = new List<int>();
         foreach(Range r in ranges)
         {
             foreach(Range rr in ranges)
             {
                  if(Overlap(r.start, r.end, rr.start, rr.end))
                       res.add(r.start);
             }
         }
         return res.ToArray();
      }
      

      【讨论】:

      • “Range”对象在哪里定义?
      • 你可以随意定义它。它至少需要一个 start 和一个 end 属性。
      • 一些有意义的参数名真的很有帮助
      【解决方案4】:
      private static bool Overlap(Range a, Range b)
      {
          if (a.Start >= b.Start && a.Start <= b.End)
          {
              return true;
          }
      
          if (b.Start >= a.Start && b.Start <= a.End)
          {
              return true;
          }
      
          return false;
      }
      
      private static bool CheckOverlap(List<Range> ranges)
      {
          for (var i = 0; i < ranges.Count - 1; i++)
          {
              for (var j = i + 1; j < ranges.Count; j++)
              {
                  if (Overlap(ranges[i], ranges[j]))
                  {
                      return false;
                  }
              }
          }
      
          return true;
      }
      

      【讨论】:

      • 注意循环。我不会将范围与自身进行比较,而只会将每个范围与其他范围进行一次比较。
      【解决方案5】:

      这是一个返回重叠点的 linq 查询。这将被 linq 简化为一个循环:

      from s1 in set1
      join s2 in set1
      on s1.end < s2.start || s2.end < s1.start
      select Tuple.Create(s1,s2);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-02-21
        • 1970-01-01
        • 1970-01-01
        • 2015-10-15
        • 1970-01-01
        • 2011-06-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多