NoSKLO和AJAX1234的现有答案都失败了。
[[1, 3], [3, 5], [5, 2], [2, 4]]
. 你问题中的尝试
fails
关于的输入
[[1, 4], [2, 3], [3, 4], [1, 2]]
是的。
正确的方法如Bowlinghawk95所述:执行
topological sort
在由输入列表诱导的有向无环图上。
我们可以实现我们自己的拓扑排序,但是让现有的图形库处理它更安全。例如,
NetworkX
:
from itertools import chain, tee
import networkx
import networkx.algorithms
# pairwise recipe from the itertools docs.
def pairwise(iterable):
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
a, b = tee(iterable)
next(b, None)
return zip(a, b)
def merge_ordering(sublists):
# Make an iterator of graph edges for the new graph. Some edges may be repeated.
# That's fine. NetworkX will ignore duplicates.
edges = chain.from_iterable(map(pairwise, sublists))
graph = networkx.DiGraph(edges)
return list(networkx.algorithms.topological_sort(graph))
这将为问题中的输入生成正确的输出
[[1,3],[3,5],[5,2],[2,4]]
如果其他答案失败了,
[[1,4],[2,3],[3,4],[1,2]]
如果您的尝试失败于:
>>> merge_ordering([[1, 3], [3, 5], [5, 2], [2, 4]])
[1, 3, 5, 2, 4]
>>> merge_ordering([['b', 'c'], ['a', 'c'], ['b', 'a'], ['a', 'c', 'd']])
['b', 'a', 'c', 'd']
>>> merge_ordering([[1, 4], [2, 3], [3, 4], [1, 2]])
[1, 2, 3, 4]
我们还可以编写一个版本,如果输入列表不能唯一确定展平形式,则会引发错误:
def merge_ordering_unique(sublists):
# Make an iterator of graph edges for the new graph. Some edges may be repeated.
# That's fine. NetworkX will ignore duplicates.
edges = chain.from_iterable(map(pairwise, sublists))
graph = networkx.DiGraph(edges)
merged = list(networkx.algorithms.topological_sort(graph))
for a, b in pairwise(merged):
if not graph.has_edge(a, b):
raise ValueError('Input has multiple possible topological orderings.')
return merged
演示:
>>> merge_ordering_unique([['b', 'c'], ['a', 'c'], ['b', 'a'], ['a', 'c', 'd']])
['b', 'a', 'c', 'd']
>>> merge_ordering_unique([[1, 3, 4], [1, 2, 4]])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 11, in merge_ordering_unique
ValueError: Input has multiple possible topological orderings.