📜  字梯 – 设置 2(双向 BFS)(1)

📅  最后修改于: 2023-12-03 15:09:21.055000             🧑  作者: Mango

字梯 - 设置 2(双向 BFS)

简介

字梯(Word Ladder)是一个单词接龙游戏,从一个单词转化为另一个单词,每次转化只能改变一个字母,且每次转化得到的中间单词都必须为英文单词。

在这个问题中,我们需要找到从起始单词到目标单词路径最短的单词接龙序列。本题的目的是使用双向 BFS 算法优化单向 BFS。

双向 BFS

双向 BFS 算法是指从起点和终点同时开始搜索,分别向中间前进,直到两个搜索集合相遇。相遇的位置即为最短路径。

相比于单向 BFS 算法,双向 BFS 可以减少搜索的时间和空间复杂度,尤其是在目标状态不清楚或是搜索空间较大的情况下。

以下是双向 BFS 算法的基本流程:

  1. 定义起点集合 begin_set 和终点集合 end_set,起点集合中只包含起始单词,终点集合中只包含目标单词。

  2. 定义两个标记 begin_visitedend_visited,表示起点集合和终点集合中的单词是否已被访问过。

  3. 定义一个 set 类型的 word_set,表示单词词典,从中查找字典中是否存在每个中间单词。

  4. 定义一个变量 step,表示起点和终点相遇时所需的最少步数,初值为 0。

  5. 循环搜索,当起点集合不为空时:

    1. 判断 begin_setend_set 中元素个数,选择小的那个集合开始搜索。
    2. 遍历当前集合中的所有单词 word,对于当前单词中的每个字符,将其分别替换成 26 个字母中的一个,生成一个新单词 new_word
    3. 判断 new_word 是否在 word_set 中,并且没有被访问过。如果是,则将其加入队列,并将其标记为已访问。
    4. 判断 end_set 中是否出现了已访问过的单词。出现则结束搜索。否则,将 begin_set 替换为新的搜索结果,step 加 1。
  6. 返回 step

代码实现

以下是双向 BFS 算法的 Python 代码实现:

def ladderLength(beginWord: str, endWord: str, wordList: List[str]) -> int:
    if endWord not in wordList:
        return 0

    begin_set, end_set = {beginWord}, {endWord}
    begin_visited, end_visited = {beginWord}, {endWord}
    word_set = set(wordList)
    step = 0

    while begin_set:
        if len(begin_set) > len(end_set):
            begin_set, end_set = end_set, begin_set
            begin_visited, end_visited = end_visited, begin_visited

        next_set = set()
        for word in begin_set:
            for i in range(len(word)):
                for c in 'abcdefghijklmnopqrstuvwxyz':
                    new_word = word[:i] + c + word[i + 1:]
                    if new_word in word_set:
                        if new_word in end_visited:
                            return step + 2
                        if new_word not in begin_visited:
                            next_set.add(new_word)
                            begin_visited.add(new_word)

        begin_set = next_set
        step += 1

    return 0
总结

双向 BFS 可以大大地提高搜索效率,尤其是在搜索空间较大的问题中。在字梯问题中,用双向 BFS 搜索的时间复杂度是单向 BFS 的一半,因为两个搜索集合相当于将搜索空间分别缩小了一半。同时,双向 BFS 在搜索过程中需要一定的额外空间开销,但是相比于单向 BFS 而言,这个额外开销是很小的。

需要注意的是,在字梯问题中,每次只能改变一个字符,因此可以将每个单词看作一个节点,将可以到达的单词看作一个节点的邻居。这样,问题就被转化为了一张无向图的最短路径问题。