【问题标题】:Find shortest path on graph with 1 character difference在图形上查找具有 1 个字符差异的最短路径
【发布时间】:2022-11-19 07:56:56
【问题描述】:

我有一个有点复杂的问题。我得到了一个单词列表(每个单词的长度相同)。我的函数中有两个词(StartNode 和 EndNode),我的任务是找到两者之间的最短路径(后续将是如何收集从 startNode 到 EndNode 的所有路径)。只有当单词最多相差 1 个单词时,它们才能连接起来。例如,TRIE 和 TREE 可以连接,因为它们仅相差一个字母 (I v E),但 TRIE 和 TWEP 不能连接,因为它们有 2 个字符差异。


我的解决方案是先建立一个邻接表,我成功实现了,然后计算一个BFS来确定startNode和endNode之间是否存在路径。我能够确定路径是否存在,但不确定如何跟踪路径。

我的尝试如下:

def shortestPath(startNode, endNode, words):
    adjList=createGraph(words)
    print(adjList)
    
    #Returns shortest path from startNode to EndNode
    visited=set()
    q=collections.deque()
    total=-1
    q.append(startNode)
    while q: 
        node=q.popleft()
        visited.add(node)
        if node==endNode: 
            if node!=startNode: 
                return total+1
        total=total+1
        for i in adjList[node]: 
            if i not in visited:
                print(i)
                q.append(i)
    
    return -1

我的 BFS 没有采用路径并且 total_length 也很明显是错误的。有什么办法可以改进我的算法吗?

示例输入:

{'POON': ['POIN', 'LOON'], 'PLEE': ['PLEA', 'PLIE'], 'SAME': [], 'POIE': ['PLIE', 'POIN'], 'PLEA': ['PLEE', 'PLIE'], 'PLIE': ['PLEE', 'POIE', 'PLEA'], 'POIN': ['POON', 'POIE'], 'LOON': ['POON']}

startWord: POON
endWord: PLEA

预期输出:

POON -> POIN -> POIE -> PLIE -> PLEA

当前输出:

POIN
LOON
POIE
PLIE
PLEE
PLEA
PLEA
6

关于我哪里出错的任何提示?

【问题讨论】:

  • 你从 POON 开始。然后,您的循环会打印两个可能的步骤(POIN、LOON),然后再次循环。然后弹出 POIN。 POON 已被访问,因此它打印 POIE。除非为每个分支保留单独的“已访问”列表,否则您无法执行 BFS。
  • @TimRoberts 是的,另一种方法是使用 DFS,但我怎么能选择不实施 DFS,因为它在确定最短路径方面效率低下,而且即使那样我也不确定如何在 DFS 中合并路径。该算法非常擅长确定最短路径,但我完全不知道如何将路径合并到其中。为每个分支保留一个单独的“访问过”列表。这是否意味着我在弹出第一个元素后附加到路径?

标签: python breadth-first-search shortest-path


【解决方案1】:

对于偶然发现这个问题的任何人,我确实找到了解决方案。一个普通的 BFS 只是计算出是否存在到节点的路径并隐式地通过最短的遍历但是如果你想显示该遍历(路径或路径长度),则有必要再保留两个计数器。

在这种情况下,我保留了前任的计数器并与源保持距离,因此我的功能变为:

def shortestPath(startNode, endNode, words):
    adjList=createGraph(words)
    print(adjList)
    
    #Returns shortest path from startNode to EndNode
    visited=set()
    
    pred={i:-1 for i in adjList} #Keep the predecessor to each node as -1 initially
    dist = {i:10000000 for i in adjList} #Initially set distance for each node from src to max
    #Distance and Predecessor: 
        
    dist[startNode]=0 #initialize distance of distance from startNode to startNode =0
    
    
    q=collections.deque()
    total=-1
    q.append(startNode)
    while q: 
        node=q.popleft()
        visited.add(node)
        if node==endNode: 
            if node!=startNode:
                findShortestPath(startNode, endNode, pred) #Pass it into another helper function since pred is already constructed
                return total+1
        total=total+1
        for i in adjList[node]: 
            
            if i not in visited:
                dist[i]=dist[node]+1
                pred[i]=node
                q.append(i)
    #If there is no available path between the two Nodes
    return -1
 

当 BFS 完成后,我们还将设置 pred 和 distance 数组。 Predecessor 将包含从开始 -> 结束的路径中的每个节点及其前任(如果不存在连接,则为 -1)。要打印出从开始到结束的路径,我们可以使用辅助函数。

此外,我还保留了距离字典。它将显示每个节点的路径。

辅助功能:

def findShortestPath(startNode, endNode, pred):
    path=[]
    crawl=endNode
    path.append(crawl)
    
    while (pred[crawl]!=-1): 
        path.append(pred[crawl])
        crawl=pred[crawl]
    
    path.reverse()
    print(path)

这是一种 Djikstra 的算法方法,但我不确定我还能如何实现这一点

【讨论】:

    【解决方案2】:

    这里的createGraph是什么???????????????????????????????????? ?????????????????????????????

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-02-04
    • 2020-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多