找到重叠项目的所有独特组合?

时间:2016-03-01 18:04:03

标签: algorithm

如果我的数据是元组列表的形式:

[(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,)]

对于这个比天真蛮力更快的算法吗?

2 个答案:

答案 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)时间)。 您还需要处理角落情况,例如,如何处理相同范围或不同范围的相等开始和结束时间。