以某种方式合并/融合元组列表

时间:2021-03-07 14:38:43

标签: python algorithm

给定一个表示边的元组列表:

edges = [(2, 4), (3, 4), (6, 8), (6, 9), (7, 10), (11, 13)]

我想合并或混合这些边以获得合并的元组列表,例如 (2, 4), (3, 4) 将合并到 (2, 4)

以上列表的最终输出应如下所示:

[(2, 4), (6, 10), (11, 13)]

我的想法是使用双 for 循环遍历列表并找到交点并将 2 条边替换为 (min(e1[0], e2[0]), max(e1[1], e2[1])) 但这种方法不会 适用于所有情况。

有什么好的想法吗?

1 个答案:

答案 0 :(得分:1)

这是我的解决方案:

edges = [(2, 4), (3, 4), (6, 8), (6, 9), (7, 10), (11, 13)]
edges = sorted(edges, key=lambda x:(x[0], -x[1]))

fused = []
i = 0
while i < len(edges):
    start,end = edges[i]
    for j in range(i+1, len(edges)):
        s,e = edges[j]
        if s <= end:
            # edges[j] is included in the fused range
            # Update end to the greater value
            end = max(e, end)
        else:
            break
    fused.append((start, end))
    del edges[i:j]
print(fused)

说明:

逻辑如下:我们按起​​始值的升序对列表进行排序。如果两个范围具有相同的起始值,我们将按其结束元素的降序 顺序排列它们。这样,具有相同起始值的两个范围将被具有较远结束值的范围“吞噬”。

既然列表以这种独特方式排序,这里有一个不错的小属性:如果从第一个范围开始,您可以决定是否要与下一个范围融合或不。如果您确实与它融合,则更新第一个范围的末尾以与“可融合”范围合并。如果您决定不与它融合,那么从第一个范围到现在的所有内容都将融合并添加到新列表中。


edges = sorted(edges, key=lambda x:(x[0], -x[1]))

按起始值的升序和结束值的降序对边进行排序。


del edges[i:j]

从原始列表中删除所有融合的范围。这很重要,因为 i 始终指向我们将开始融合的新范围。

相关问题