算法 – 重叠时查找重叠间隔很少见

我有一个巨大的数据库表,有n个整数区间(例如{1-5},{4-16},{6434-114343}),需要找出哪些区间相互重叠.有一个丰富的similar questions on SO,但不同的是我需要返回,分别为每个区间,重叠区间的集合.

      ------------------ A -------------------
    ------ B -------               ----- D -----
          --------- C --------- 

对于此示例,输出将为A:{B,C,D} B:{A,C} C:{A,B} D:{A}

最坏的情况是,所有间隔可以相互重叠,产生大小为O(n2)的输出.这并不比天真的解决方案好(比较每对间隔).然而,在实践中,我知道我的间隔很少会与其他间隔重叠,当它们发生时,最多只有5个其他间隔.

鉴于此信息,我该如何解决问题? (最好,我想要一个SQL查询解决方案,因为数据在数据库中,但我认为只有常规的算法解决方案是可能的.)

最佳答案
构建一个间隔开始和结束的排序序列,然后遍历它,每次更新当前间隔列表时,报告任何新找到的交叉点.

像这样的东西:

std::vector<TBorder> borders;
for(auto i=intervals.begin();i!=intervals.end();++i)
{
    borders.push_back(TBorder(i.Start(),Start));
    borders.push_back(TBorder(i.End(),End));
}
std::sort(borders.begin(),borders.end());
std::set<int> currentIntervals;
for(auto b=borders.begin();b!=borders.end();++b)
{
    if(b.IsEnd())
        currentIntervals.erase(b.IntervalIndex());
    else
    {
        currentIntervals.insert(b.IntervalIndex());
        if(currentIntervals.size()>1)
            ReportIntersection(currentIntervals);
    }
}

通常它是O(n * log n)(假设交叉点的数量是O(1)).

但是,如果你已经有间隔排序,例如开始,可能的排序可以在O(n)中完成(再次假设交叉点的数量是O(1)).

转载注明原文:算法 – 重叠时查找重叠间隔很少见 - 代码日志