欢迎访问LeetCode题解合集
题目描述
字典 wordList
中从单词 beginWord
和 endWord
的 转换序列 是一个按下述规格形成的序列:
-
序列中第一个单词是
beginWord
。 -
序列中最后一个单词是
endWord
。 -
每次转换只能改变一个字母。
-
转换过程中的中间单词必须是字典
wordList
中的单词。
给你两个单词 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 \le beginWord.length \le 10$
- endWord.length == beginWord.length
- $1 \le wordList.length \le 5000$
- wordList[i].length == beginWord.length
- beginWord、endWord 和 wordList[i] 由小写英文字母组成
- beginWord != endWord
- wordList 中的所有字符串 互不相同
题解:
建图 + 广搜。
提前预处理出 beginWord
和 wordList
中的每个字符串变换后下一个可能的字符串,并根据这个建图。BFS
找出 beginWord
到 endWord
的最短路径即可。
时间复杂度:$O(n * L^2)$
额外空间复杂度:$O(n^2 * L)$
class Solution {
public:
unordered_map<string, vector<string>> g;
unordered_map<string, int> dis;
unordered_set<string> cand;
void getNexts( const string& st, const vector<string>& wordList ) {
string s = st;
for ( int i = 0; st[i]; ++i ) {
for ( s[i] = 'a'; s[i] <= 'z'; ++s[i] ) {
if ( s[i] != st[i] && cand.find( s ) != cand.end() )
g[st].emplace_back( s );
}
s[i] = st[i];
}
for ( const auto& it : wordList ) {
s = it;
for ( int i = 0; it[i]; ++i ) {
for ( s[i] = 'a'; s[i] <= 'z'; ++s[i] ) {
if ( s[i] != it[i] && cand.find( s ) != cand.end() )
g[it].emplace_back( s );
}
s[i] = it[i];
}
}
}
int bfs( const string& st, const string& ed ) {
queue<string> q;
unordered_set<string> vis;
q.push( st );
dis[st] = 1;
vis.insert( st );
string now;
while ( q.size() ) {
now = q.front();
q.pop();
for ( const auto& it : g[now] ) {
if ( vis.find( it ) != vis.end() ) continue;
dis[it] = dis[now] + 1;
if ( it == ed ) return dis[it];
vis.insert( it );
q.push( it );
}
}
return 0;
}
int ladderLength(string beginWord, string endWord, vector<string>& wordList) {
for( const auto& it : wordList )
cand.insert( it );
if ( cand.find( endWord ) == cand.end() ) return 0;
getNexts( beginWord, wordList );
return bfs( beginWord, endWord );
}
};
/*
时间:200ms,击败:51.20%
内存:30.8MB,击败:22.13%
*/
也可以直接广搜,不建图。
时间复杂度:$O(n * L^2)$
额外空间复杂度:$O(n * L)$
class Solution {
public:
int ladderLength(string beginWord, string endWord, vector<string>& wordList) {
unordered_set<string> cand;
unordered_map<string, int> dis;
for( const auto& it : wordList )
cand.insert( it );
if ( cand.find( endWord ) == cand.end() ) return 0;
queue<string> q;
q.push( beginWord );
dis[beginWord] = 1;
string now, ans;
while ( q.size() ) {
now = q.front();
q.pop();
ans = now;
for ( int i = 0; now[i]; ++i ) {
for ( ans[i] = 'a'; ans[i] <= 'z'; ++ans[i] ) {
if ( ans[i] != now[i] && cand.find( ans ) != cand.end() ) {
if ( dis.count( ans ) ) continue;
dis[ans] = dis[now] + 1;
if ( ans == endWord ) return dis[ans];
q.push( ans );
}
}
ans[i] = now[i];
}
}
return 0;
}
};
/*
时间:128ms,击败:75.34%
内存:15.5MB,击败:36.19%
*/