使用线段树查找重叠区间的总长度?

Posted

技术标签:

【中文标题】使用线段树查找重叠区间的总长度?【英文标题】:Find the total length of overlapped intervals using segment tree? 【发布时间】:2013-01-25 13:31:52 【问题描述】:

我们有一些区间,例如 [1;4] [7;13] [9;14] 输入应该返回 3+6+1=10。 在可以动态插入或删除区间的情况下,有什么方法可以使用线段树来找到这些区间的总长度?

P.S.:我想在不使用段树的情况下这样做,但时间复杂度并不让我满意。

提前谢谢你

【问题讨论】:

您有多少个间隔以及最大最小位置和迭代长度。有多少请求得到总和,有多少插入? 间隔是否按照您的示例进行排序? @AndyT 是的,我可以先对它们进行排序 区间可以动态插入或删除。 【参考方案1】:

假设间隔存储在数组[m,n] 中。 另一个假设是数组已排序。

您需要做的就是找到较小的差异:

 int totalIntervales = 0;
 for(int index = 0; index < array.length ; index++)
 
     int currentIntrval = array[index, 1] - array[index, 0];
     int differnceFromPrevious = array[index, 1] - array[index- 1, 1]
     totalIntervale += currentIntrval  > differnceFromPrevious ? differnceFromPrevious : currentIntrval;
 
 return totalIntervale;

小心处理 0 位置。

【讨论】:

我认为当第二个区间完全包含在第一个区间内时,您的算法存在错误。考虑集合 [1,4][2,3]。您的算法会说间隔为 2。解决方法是检查 differenceFromPrevious 是否为非负数。否则,它似乎工作。 (编辑因为我忘记点击“输入”会提交评论) 实际上,经过进一步考虑,我认为您的算法效果不佳。以 [1, 5][1, 2][2, 4] 为例。您的算法会报告 4 - 3 + 2 = 3。【参考方案2】:

Kobi/Maureinik 的答案非常接近,但我必须为 maxEnd 添加一个变量并检查 differenceFromPrevious 是否为非负数。该算法仍然假设范围是在开始元素上排序的(即 array[i, 0])

int totalInterval = array[0, 1] - array[0, 0];
int maxEnd = array[0, 1];
for(int index = 1; index < array.length ; index++) 
  int currentIntrval = array[index, 1] - array[index, 0];
  int differnceFromPrevious = array[index, 1] - maxEnd;
  if(differenceFromPrevious >= 0) 
    totalInterval += (currentIntrval > differnceFromPrevious) ? differnceFromPrevious : currentIntrval;
  
  maxEnd = (maxEnd >= array[index, 1]) ? maxEnd : array[index, 1];

return totalInterval;

编辑:修复了无效的原始 totalInterval 逻辑的意外副本。如果 differenceFromPrevoius

【讨论】:

以上是关于使用线段树查找重叠区间的总长度?的主要内容,如果未能解决你的问题,请参考以下文章

区间覆盖(线段树)

线段树

线段树

线段树 (区间覆盖模板)

线段树 入门详解

(使用线段树实现的)扫描线算法