Algorithm 在间隔列表中搜索间隔重叠?
假设[a,b]表示实线上从a到b的间隔,a 你能把它们分成两个列表吗?一个是间隔开始的列表,另一个是间隔结束的列表 通过这种方式,您可以将y与间隔开始列表中的项目进行比较(比如通过二进制搜索),从而在此基础上减少候选项 然后可以将x与“间隔结束”列表中的项目进行比较 编辑 案例:一次性 如果你在一次性情况下只比较单个时间间隔和时间间隔列表,我不相信排序能帮你解决问题 通过对所有的x进行线性搜索以剔除任何不可能的间隔,然后对剩余的y进行另一次线性搜索,您可以减少您的总工作量。虽然这仍然是O(n),但如果没有这一点,您将进行2n次比较,而平均而言,您只能以这种方式进行(3n-1)/2次比较 我相信这是最好的,你可以做一个未排序的名单 案例:预排序不算数Algorithm 在间隔列表中搜索间隔重叠?,algorithm,Algorithm,假设[a,b]表示实线上从a到b的间隔,ax和a
如果您将重复将单个间隔与此间隔列表进行比较,并对列表进行预排序,则可以获得更好的结果。上述过程仍然适用,但通过对第一个列表进行二进制搜索,然后对第二个列表进行二元搜索,您可以得到O(m log n),而不是O(mn),其中m是正在比较的单个间隔的数量。注意,仍然提供了减少总比较的优势。[2m log n与m(3(log n)-1)/2相比]您可以同时按左端和右端进行排序,并使用两个列表来消除无重叠值。如果列表按左端排序,则测试范围右端右侧的间隔都不能重叠。如果列表按右端排序,则左端左侧的间隔都不能重叠测试范围的所有部分可能重叠 例如,如果间隔为
[1,4], [3,6], [4,5], [2,8], [5,7], [1,2], [2,2.5]
您发现与[3,4]
重叠,然后按测试的左端排序并标记右端的位置(右端刚好大于其值,因此4
包含在范围内)
您知道[5,7]
不能重叠,然后按测试的右端排序并标记左端的位置
[1,2], [2,2.5], *, [1,4], [4,5], [3,6], [5,7], [2,8]
你知道[1,2]
和[2,2.5]
不能重叠
不确定这样做的效率有多高,因为您必须进行两次排序和搜索。A是一种数据结构,通常用于提高二维碰撞检测的效率
我认为你可以想出一个类似的一维结构。这需要一些预先计算,但会导致O(logn)性能
基本上,从覆盖所有可能间隔的根“节点”开始,当向树中添加节点时,您可以决定它是落在中点的左侧还是右侧。如果它穿过中点,您可以将其分成两个间隔(但记录原始父节点)你可以对树的深度设置一个限制,这可以节省内存和提高性能,但会让事情变得复杂一些(你需要在节点中存储一个间隔列表)
然后,在检查间隔时,基本上可以找到插入该间隔时将插入的所有叶节点,检查这些节点内的部分间隔是否相交,然后将记录的间隔报告为“原始”父节点。[a,b]与[x,y]重叠iff b>x和a
O(n)
是您得到的最好的数据结构(通常更容易根据指定算法的数据结构进行思考)
在这种情况下,您的问题不完整:
- 你有完整的清单吗,还是你自己创造的
- 您只需要执行一个或多个这样的查找吗
- 您对它应该支持的操作及其频率有什么估计吗
一个简单的实现是一个有序的(按coordonate)列表,在其中插入所有带有标志start/end和段号的段结束。这样,通过解析它(仍然是O(n),但如果您还需要重叠的所有段的列表,我怀疑您是否可以加快速度),并跟踪在“检查点”未关闭的所有打开的段。为了完整性起见,我想补充一点,对于这类问题,有一个众所周知的数据结构,称为(惊喜,惊喜)。它基本上是一个扩展的平衡树(红黑,AVL,您选择)它存储按其左(低)端点排序的间隔。扩展是每个节点在其子树中存储最大的右(高)端点。此树允许您在O(logn)时间内查找所有重叠间隔
CLRS 14.3中对其进行了描述。+1,因为它使我的工作日变得更加有趣。但是交叉点不是需要O(n)个时间吗?如果列表长度为n个元素,则
[1,2], [2,2.5], *, [1,4], [4,5], [3,6], [5,7], [2,8]