如何找到对列表中的所有对都有重叠?

时间:2013-08-06 10:45:59

标签: c algorithm

包含2个数字对的列表的数组:[n1 n2 ...]

每个元素都是<first second >

如何有效地找到所有可能的重叠?

我只能想到复杂度为O(n2)的蛮力方法。

此问题也可能适用于时间重叠。

3 个答案:

答案 0 :(得分:3)

start time排序时间。 然后检查下一个时段start time是否高于当前广告位end time

TimeSlot[] slots;
sort(slots, slots.start_time);
for(i = 0 to (slots.length - 1)){
    if(slots[i].end_time > slots[i + 1].start_time) reportConflict();
}

它的作用时间为O(n log n),其中n是时段数

如果您需要查找所有冲突对,则需要修改算法:

TimeSlot[] slots;
sort(slots, slots.start_time);
for(i = 0 to (slots.length - 1)){
    int j = i + 1;
    while(j < (slots.length - 1) and slots[i].end_time > slots[j].start_time){
        reportConflict(i, j);
        ++j;
    }
}

它的作用时间为O((n log n) + c),其中n是时段数,c是冲突数

如果只需要重叠次数,则使用二进制搜索有更好的算法:

TimeSlot[] slots;
int overlapsNumber = 0;
sort(slots, slots.start_time);
for(i = 0 to (slots.length - 1)){
    int j = BinarySearch(slots, i);
    overlapsNumber += (j - i);
}

//Finds index j which is the greatest index that slots[j].start_time < slots[i].end_time
int BinarySearch(TimeSlot[] sortedSlots, int pos){
    int b = pos, e = sortedSlots.length - 1;
    int ans = b;
    while(b < e){
        int mid = (e + b) / 2;
        if(sortedSlots[mid].start_time < sortedSlots[pos].end_time){
            ans = mid;
            b = mid + 1;
        } else {
            e = mid - 1;
        }
    }
    return ans;

它及时工作O(n log n)

答案 1 :(得分:2)

这样做的算法很简单。

  1. 根据开始时间对间隔进行排序
  2. 浏览列表,检查当前元素的结束时间是否大于下一个元素的开始时间。
  3. 利润
  4. 编辑

    要检测所有重叠(即跨越多个间隔的重叠),请执行以下操作:

    1. 根据开始时间对您的间隔进行排序
    2. 检查当前元素的结束时间,看它是否大于或等于下一个元素的开始时间。
    3. 如果这是重叠的情况标记间隔,则检查下一个+ 1个元素的重叠开始时间。继续这一直到你结束。
    4. 对列表中的所有间隔执行此操作。

      请注意,两个“算法”都在O(n log n)中运行。第一个因为排序需要O(n log n)并且在列表中运行需要O(n)给出O(n log n + n) = O(n log n)。对于第二个排序仍为O(n log n),现在通过列表O((1/2)n^2 + (1/2)n) = O(n^2)提供O(n log n + n^2) = O(n^2)

      再次编辑
      这样做的更好的方法显然是在an interval tree中保留间隔。

答案 2 :(得分:0)

只需按start_time对其进行排序,然后遍历列表,检查current.end_time之后是否next.start_time