给定一个表示边的元组列表:
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]))
但这种方法不会
适用于所有情况。
有什么好的想法吗?
答案 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
始终指向我们将开始融合的新范围。