如果我的数据是元组列表的形式:
[(uid, start_time, end_time)]
我想找到所有在时间上重叠的uids的独特组合。例如,如果我有一个如下列表:
[(0, 1, 2),
(1, 1.1, 3),
(2, 1.5, 2.5),
(3, 2.5, 4),
(4, 4, 5)]
我想得到输出:
[(0,1,2), (1,3), (0,), (1,), (2,), (3,), (4,)]
对于这个比天真蛮力更快的算法吗?
答案 0 :(得分:1)
首先,按开始时间对元组进行排序。保留一堆活动元组,其中最早的结束时间位于顶部。
然后,您浏览已排序的列表并将元组添加到活动集。这样做,您还可以检查是否需要删除元组。如果是这样,您可以报告间隔。为避免重复报告,仅在自上次报告以来已向活动集添加新元组时报告新的时间间隔。
这是一些可视化想法的伪代码:
sort(tuples)
activeTuples := new Heap
bool newInsertAfterLastReport = false
for each tuple in tuples
while activeTuples is not empty and activeTuples.top.endTime <= tuple.startTime
//the first tuple from the active set has to be removed
if newInsertAfterLastReport
report activeTuples
newInsertAfterLastReport = false
activeTuples.pop()
end while
activeTuples.insert(tuple)
newInsertAfterLastReport = true
next
if activeTuples has more than 1 entry
report activeTuples
使用您的示例数据集:
data = [(0, 1, 2), (1, 1.1, 3), (2, 1.5, 2.5), (3, 2.5, 4), (4, 4, 5)]
tuple activeTuples newInsertAfterLastReport
---------------------------------------------------------------------
(0, 1, 2) [] false
[(0, 1, 2)] true
(1, 1.1, 3)
[(0, 1, 2), (1, 1.1, 3)]
(2, 1.5, 2.5)
[(0, 1, 2), (2, 1.5, 2.5), (1, 1.1, 3)]
(3, 2.5, 4) -> report (0, 1, 2)
[(2, 1.5, 2.5), (1, 1.1, 3)] false
[(1, 1.1, 3)]
[(1, 1.1, 3), (3, 2.5, 4)] true
(4, 4, 5) -> report (1, 3) false
[(3, 2.5, 4)]
[]
[(4, 4, 5)]
实际上,我会删除if activeTuples has more than 1 entry
部分并始终在最后报告。这会产生(4)
的额外报告,因为它未包含在任何先前的报告中(而(0) ... (3)
是)。
答案 1 :(得分:0)
我认为这可以在O(n lg n + n o)时间内完成,其中o是输出的最大大小(在最坏的情况下,o可能是n)。 为每个start_time或end_time构建一个3元组,如下所示:第一个组件是输入元组的start_time或end_time,第二个组件是输入元组的id,第三个组件是它的start_time还是end_time 。现在你有2n 3元组。按第一个组件的升序对它们进行排序。 现在开始扫描从最小到最大的3元组列表。每次开始一个范围时,将其id添加到平衡二叉搜索树(在O(lg o)时间内),并输出树的内容(在O(o)中),每次范围结束时,删除其id从树上(在O(lg o)时间)。 您还需要处理角落情况,例如,如何处理相同范围或不同范围的相等开始和结束时间。