我有一个这样的元组列表。
a = [(1,2),(1,3),(1,4),(2,5),(6,5),(7,8)]
在此列表中,1与2有关,然后2与5有关,而5与6有关,因此1与6有关。类似地,我需要找到元组中其他元素之间的关系。我需要一个采用输入值和输出的函数,如下所示:
input = (1,6) #output = True
input = (5,3) #output = True
input = (2,8) #output = False
我不了解itertools或map函数。它们可以用来解决这类问题吗? 并且出于好奇和兴趣,我在哪里可以找到这些类型的问题来解决,以及在现实生活中遇到的这些类型的问题在哪里?
答案 0 :(得分:6)
可以通过将元组视为图形中的边来轻松完成此操作。然后将问题简化为检查两个节点之间是否存在路径。
为此存在许多不错的库,请参见例如networkx
import networkx as nx
a = [(1,2),(1,3),(1,4),(2,5),(6,5),(7,8)]
G = nx.Graph(a)
nx.has_path(G, 1, 6) # True
nx.has_path(G, 5, 3) # True
nx.has_path(G, 2, 8) # False
答案 1 :(得分:2)
这个答案here很好地将您的问题表示为图问题,其中每次您需要运行算法时,都需要检查输入顶点之间是否存在路径。然后,每个查询的时间复杂度取决于基础图的大小,顺序,直径和程度。
但是,如果您打算使用同一数组a
多次运行此算法,则可能值得对输入图进行一些预处理以首先找到连接的组件(Wikipedia : connected components)。在这种情况下,您可以为每个查询获取恒定时间。这是我建议的代码:
# NOTE : tested using python 3.6.1
# WARNING : no input sanitization
a = [(1,2),(1,3),(1,4),(2,5),(6,5),(7,8)]
n = 8 # order of the underlying graph
# prepare graph as lists of neighbors for every vertex, i.e. adjacency lists (extra unused vertex '0', just to match the value range of the problem)
graph = [[] for i in range(n+1)]
for edge in a:
graph[edge[0]].append(edge[1])
graph[edge[1]].append(edge[0])
print( "graph : " + str(graph) )
# list of unprocessed vertices : contains all of them at the beginning
unprocessed_vertices = {i for i in range(1,n+1)}
# subroutine to discover the connected component of a vertex
def build_component():
component = [] # current connected component
curr_vertices = {unprocessed_vertices.pop()} # locally unprocessed vertices, initialize with one of the globally unprocessed vertices
while len(curr_vertices) > 0:
curr_vertex = curr_vertices.pop() # vertex to be processed
# add unprocessed neighbours of current vertex to the set of vertices to process
for neighbour in graph[curr_vertex]:
if neighbour in unprocessed_vertices:
curr_vertices.add(neighbour)
unprocessed_vertices.remove(neighbour)
component.append(curr_vertex)
return component
# main algorithm : graph traversal on multiple connected components
components = []
while len(unprocessed_vertices) > 0:
components.append( build_component() )
print( "components : " + str(components) )
# assign a number to each component
component_numbers = [None] * (n+1)
curr_number = 1
for comp in components:
for vertex in comp:
component_numbers[vertex] = curr_number
curr_number += 1
print( "component_numbers : " + str(component_numbers) )
# main functionality
def is_connected( pair ):
return component_numbers[pair[0]] == component_numbers[pair[1]]
# run main functionnality on inputs : every call is executed in constant time now, regardless of the size of the graph
print( is_connected( (1,6) ) )
print( is_connected( (5,3) ) )
print( is_connected( (2,8) ) )
我真的不知道最有可能遇到此问题的情况,但是我想它可以在应用程序中执行一些群集任务,或者也许您是否想知道是否可以从一个地方转到另一个地方。另一个。如果图形的边缘表示模块之间的依赖关系,则此问题将告诉您两个部分是否相互依赖,因此可能在编译或管理大型项目时有一些潜在的应用程序。潜在的问题是“连接组件”问题,这是我们知道的多项式算法中的问题。
使用图对这类问题建模通常非常有用,因为这些对象的结构非常简单,并且在大多数情况下,我们可以将原始问题简化为图上众所周知的问题。