我试图写一些代码来计算两组区间A - B的差异,区间端点是整数,但我正在努力找到有效的解决方案,任何建议都将非常感谢示例:[(1,4),(7,9)] - [(3,5)] = [(1,3),(7,9)]
这是我迄今为止最好的尝试(两个列表已经排序)
class tp():
def __repr__(self):
return '(%.2f,%.2f)' % (self.start, self.end)
def __init__(self,start,end):
self.start=start
self.end=end
z=[tp(3,5)] #intervals to be subtracted
s=[tp(1, 4)),tp(7, 9), tp(3,4),tp(4,6)]
for x in s[:]:
if z.end < x.start:
break
elif z.start < x.start and z.end > x.start and z.end < x.end:
x.start=z.end
elif z.start < x.start and z.end > x.end:
s.remove(x)
elif z.start > x.start and z.end < x.end:
s.append(tp(x.start,z.start))
s.append(tp(z.end,x.end))
s.remove(x)
elif z.start > x.start and z.start < x.end and z.end > x.end:
x.end=z.start
elif z.start > x.end:
continue
3条答案
按热度按时间t3psigkw1#
使操作有效的唯一方法是保持区间列表排序和不重叠(这可以在
O(n log n)
中完成)。[参见下面的注解]。在两个列表都已排序且不重叠的情况下,任何集合操作(并集、交集、差集、对称差集)都可以通过简单的合并来执行。
合并操作很简单:同时按顺序遍历两个参数的端点。(注意,每个区间列表的端点都是排序的,因为我们要求区间不重叠。)对于发现的每个端点,判断它是否在结果中。如果结果当前有奇数个端点,并且新的端点不在结果中,则将其添加到结果中;类似地,如果结果当前具有偶数个端点并且新端点在结果中,则将其添加到结果中。在此操作结束时,结果是端点列表,在间隔开始和间隔结束之间交替。
在Python中是这样的:
注意事项
1.间隔
[a, b)
和[b, c)
不重叠,因为它们不相交;b
只属于第二个。这两个区间的并集仍然是[a,c)
。但是为了这个答案中的函数的目的,最好也要求区间不相邻,通过扩展“不重叠”的定义来包括区间相邻的情况;否则,我们会冒着发现输出中不必要地包含了邻接点的风险。(严格地说,这并不是错误的,但是如果输出是确定性的,那么测试函数就更容易了。)下面是一个函数的示例实现,该函数将任意的区间列表规范化为一个排序的、不重叠的区间。
w8ntj3qf2#
这个问题可以用扫描线算法来解决。其思想是将两个集合中的区间的所有起点保存在一个有序数组中,并将终点保存在另一个有序数组中,用它们属于哪个集合的信息来标记它们。
现在有两个指针,一个指向每个数组的开头。在循环中,递增一个指向最小值的指针,添加从a开始直到以b或a结束的间隔。例如,对于上面的内容,我们将按此顺序迭代点
这导致在区间数方面的线性解。
5us2dqdw3#
另一个使用numpy的实现。我假设,因为我认为使用 integer endpoints 更自然,区间是封闭的。对于我下面建议的方法,我们绝对需要照顾(半封闭)区间,包括-infinity和+infinity。