算法学习:双向BFS

理论

解决的问题

在朴素的 BFS 实现中,空间的瓶颈主要取决于搜索空间中的最大宽度。

解决的方法

同时从两个方向开始搜索,一旦搜索到相同的值,意味着找到了一条联通起点和终点的最短路径。


实现的基本思路
  1. 创建「两个队列」分别用于两个方向的搜索;
  2. 创建「两个哈希表」用于表示「访问过的节点」;
  3. 为了尽可能让两个搜索方向“平均”,每次从队列中取值进行扩展时,先判断哪个队列容量较少,队列数据较少的先执行;
  4. 如果在搜索过程中「搜索到对方搜索过的节点」,说明找到了最短路径;如果结束搜索过程后,还没有找到,表示不连通。

算法实践

127. 单词接龙

问题描述

字典 wordList 中从单词 beginWordendWord转换序列 是一个按下述规格形成的序列 beginWord -> s1 -> s2 -> ... -> sk
每一对相邻的单词只差一个字母。
对于 1 <= i <= k 时,每个 si 都在 wordList 中。注意, beginWord 不需要在 wordList 中。
sk == endWord
给你两个单词 beginWordendWord 和一个字典 wordList ,返回 从 beginWordendWord 的 最短转换序列 中的 单词数目 。如果不存在这样的转换序列,返回 0

示例
输入:beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log","cog"]
输出:5
解释:一个最短转换序列是 "hit" -> "hot" -> "dot" -> "dog" -> "cog", 返回它的长度 5。

输入:beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log"]
输出:0
解释:endWord "cog" 不在字典中,所以无法进行转换。
解题思路
  1. 先判断endWord是否在wordList中,如果不在,直接返回0
  2. 创建两个队列分别表示2个方向的搜索;
  3. 对两个队列进行bfs,优先跑队列长度小的队列;
  4. 当搜索过程中「搜索到对方搜索过的节点」,返回搜索次数。
代码示例(JAVA)
class Solution {
    public int ladderLength(String beginWord, String endWord, List wordList) {
        Set wordSet = new HashSet<>();
        for (String word : wordList) {
            wordSet.add(word);
        }
        if (!wordList.contains(endWord)) {
            return 0;
        }

        Set startSet = new HashSet<>();
        Set endSet = new HashSet<>();
        Set visited = new HashSet<>();
        startSet.add(beginWord);
        endSet.add(endWord);

        int len = 1;
        while (!startSet.isEmpty() && !endSet.isEmpty()) {
            // 优先跑少的部分
            if (startSet.size() > endSet.size()) {
                Set temp = startSet;
                startSet = endSet;
                endSet = temp;
            }

            Set temp = new HashSet<>();
            for (String word : startSet) {
                char[] chars = word.toCharArray();
                for (int i = 0; i < chars.length; i++) {
                    char old = chars[i];
                    for (char k = 'a'; k <= 'z'; k++) {
                        if (chars[i] == k) {
                            continue;
                        }
                        chars[i] = k;
                        String newString = String.valueOf(chars);
                        if (endSet.contains(newString)) {
                            return len + 1;
                        }
                        if (!visited.contains(newString) && wordSet.contains(newString)) {
                            temp.add(newString);
                            visited.add(newString);
                        }
                        chars[i] = old;
                    }
                }
            }
            startSet = temp;
            len++;
        }
        return 0;
    }
}
类似的题目

433. 最小基因变化

你可能感兴趣的:(算法学习:双向BFS)