包含2个数字对的列表的数组:[n1 n2 ...]
每个元素都是<first second >
。
如何有效地找到所有可能的重叠?
我只能想到复杂度为O(n2)的蛮力方法。
此问题也可能适用于时间重叠。
答案 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)
这样做的算法很简单。
编辑
要检测所有重叠(即跨越多个间隔的重叠),请执行以下操作:
对列表中的所有间隔执行此操作。
请注意,两个“算法”都在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
。