LeetCode 127. Word Ladder

107 阅读1分钟

LeetCode 127. Word Ladder

字典 wordList 中从单词 beginWord **和 endWord 的 转换序列 是一个按下述规格形成的序列 beginWord -> s1 -> s2 -> ... -> sk

  • 每一对相邻的单词只差一个字母。
  •  对于 1 <= i <= k 时,每个 si 都在 wordList 中。注意, beginWord **不需要在 wordList 中。
  • sk == endWord

给你两个单词 **beginWord **和 endWord 和一个字典 wordList ,返回 从 beginWord 到 endWord 的 最短转换序列 中的 单词数目 。如果不存在这样的转换序列,返回 0 。

 

示例 1:

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

示例 2:

输入: beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log"]
输出: 0
解释: endWord "cog" 不在字典中,所以无法进行转换。

 

提示:

  • 1 <= beginWord.length <= 10
  • endWord.length == beginWord.length
  • 1 <= wordList.length <= 5000
  • wordList[i].length == beginWord.length
  • beginWordendWord 和 wordList[i] 由小写英文字母组成
  • beginWord != endWord
  • wordList 中的所有字符串 互不相同

算法

(最短路,BFS) O(n2n^2L)
我们对问题进行抽象:
将单词看做点,如果两个单词可以相互转化,则在相应的点之间连一条无向边。那问题就变成了求从起点到终点的最短路。

然后考虑如何建图,有两种方式:

枚举所有单词对,然后判断是否可以通过改变一个字母相互转化,时间复杂度 O(n2n^2L);
枚举每个单词,然后枚举该单词的每一位字母,再枚举这一位的所有备选字母,然后再判断改变后的字符串是否存在,时间复杂度 O(26nL2L^2)。
我们要根据数据范围选择使用哪种建图方式,如果 26L>n,则用第二种,否则用第一种。经测试,早先leetcode上两种方式都是可以AC的,但后来增加了 n 的大小,但并未增加 L 的大小,所以第二种建图方式会超时,于是我们选择第一种建图方式即可。

由于边权都相等,所以可以用BFS求最短路。

时间复杂度分析

建图,通过上述分析可知,时间复杂度是 O(26nL2L^2);
求最短路用的是BFS,每个节点仅会遍历一次,每个点遍历时需要O(L)的计算量,所以时间复杂度是 O(nL);
所以总时间复杂度是 O(26nL2L^2)。 ###C++ 代码

class Solution {
public:
    int ladderLength(string beginWord, string endWord, vector<string>& wordList) {
        unordered_set<string> S;
        unordered_map<string, int> dist;
        queue<string> q;
        dist[beginWord] = 1;
        q.push(beginWord);
        for (auto word: wordList) S.insert(word);

        while (q.size()) {
            auto t = q.front();
            q.pop();
            string r = t;
            for (int i = 0; i < t.size(); i ++ ) {
                t = r;
                for (char j = 'a'; j <= 'z'; j ++ )
                    if (r[i] != j) {
                        t[i] = j;
                        if (S.count(t) && dist.count(t) == 0) {
                            dist[t] = dist[r] + 1;
                            if (t == endWord) return dist[t];
                            q.push(t);
                        }
                    }
            }
        }
        return 0;
    }
};