我有两个范围,想要检查它们是否在Python(v3.5)中重叠。这些是一些解决方案。
1a :使用范围:
的集合intersection
def overlap_intersection_set(range1, range2):
return bool(set(range1).intersection(range2))
1b :将set intersection
与两套使用:
def overlap_intersection_two_sets(range1, range2):
return bool(set(range1).intersection(set(range2)))
2 :使用any
和范围in
:
def overlap_any(range1, range2):
return any([i1 in range2 for i1 in range1])
我一直在努力计算这些方法的成本,主要是在时间方面,但空间复杂性也可能相当大。
设置交叉点的Python Wiki page "Time Complexity"列表(平均大小写):
交叉点s& t(平均情况):
O(min(len(s), len(t))
(替换" min"用" max"如果t不是一组)
对于解决方案 1b ,我因此假定O(min(len(range1), len(range2))
,加上两次来自范围的集合创建。我认为bool
函数非常便宜。
对于解决方案 1a :O(max(len(range1), len(range2))
,再加上一次从范围创建的设置。
对于解决方案 2 (any
):我没有找到很多关于复杂性的文档,无论是any
还是范围in
。对于后者,我假设范围的行为类似于列表,这对于每个O(n)
调用意味着in
,因此导致O(n*m)
与n=len(range1)
和{{1} }。同时,只要找到匹配项,m=len(range2)
就会生成快捷方式,并且可以节省集合创建。
因此,我的问题涉及算法复杂性以及它们特定于Python的实现:
any
功能真的有多贵?bool()
是否真的与列表中的行为相同(in
)?这并不容易根据经验进行评估,因为实际计算时间很大程度上取决于范围的属性,即找到重叠元素的早期及其大小。这就是为什么我在寻找更具分析性的解释。
答案 0 :(得分:1)
上述算法独立于范围的大小,也可以处理非整数范围。
类似的东西:
def is_overlapped(r1, r2):
if r1.lowest > r2.lowest:
r1, r2 = r2, r1
return r1.highest > r2.lowest
更全面的实施:
from collections import namedtuple
class Range(namedtuple('Range', 'lowest, highest')):
__slots__ = ()
def __new__(_cls, lowest, highest):
'Enforces lowest <= highest'
if lowest > highest:
lowest, highest = highest, lowest
return super().__new__(_cls, lowest, highest)
def is_overlapped(r1, r2):
r1, r2 = sorted([r1, r2])
return r1.highest > r2.lowest
if __name__ == '__main__':
range1, range2 = Range(4, -4), Range(7, 3)
assert is_overlapped(range2, range1) == is_overlapped(range1, range2)
print(is_overlapped(range2, range1)) # True