图:BFS
睡不醒的鲤鱼 2022-05-13 每日一题 LeetCode
# 0126. 单词接龙 II (opens new window)
题目
按字典 wordList 完成从单词 beginWord 到单词 endWord 转化,一个表示此过程的 转换序列 是形式上像 beginWord -> s1 -> s2 -> ... -> sk 这样的单词序列,并满足:
- 每对相邻的单词之间仅有单个字母不同。
- 转换过程中的每个单词 si(1 <= i <= k)必须是字典 wordList 中的单词。注意,beginWord 不必是字典 wordList 中的单词。
- sk == endWord
给你两个单词 beginWord 和 endWord ,以及一个字典 wordList 。请你找出并返回所有从 beginWord 到 endWord 的 最短转换序列 ,如果不存在这样的转换序列,返回一个空列表。每个序列都应该以单词列表 [beginWord, s1, s2, ..., sk] 的形式返回。
从 beginWord 和 endWord 进行双向 BFS 构建单词转换图,然后再从 beginWord 进行一次 DFS 即可。
代码
class Solution {
unordered_map<string, vector<string>> children;
vector<vector<string>> ans;
vector<string> path;
public:
vector<vector<string>> findLadders(string beginWord, string endWord, vector<string>& wordList) {
unordered_set<string> dict(wordList.begin(), wordList.end());
if (!dict.count(endWord)) return ans;
unordered_set<string> s1{beginWord}, s2{endWord};
bool found = false, beginToEnd = true;
while (!s1.empty() && !s2.empty() && !found) {
if (s1.size() > s2.size()) {
swap(s1, s2);
beginToEnd = !beginToEnd;
}
for (string w: s1) dict.erase(w);
for (string w: s2) dict.erase(w);
unordered_set<string> s;
for (string word: s1) {
string cur = word;
for (int i = 0; i < word.length(); i++) {
char ch = word[i];
for (char j = 'a'; j <= 'z'; j++) {
word[i] = j;
string parent = cur, child = word;
if (!beginToEnd) swap(parent, child);
if (s2.count(word)) {
found = true;
children[parent].push_back(child);
} else if (dict.count(word) && !found) {
s.insert(word);
children[parent].push_back(child);
}
}
word[i] = ch;
}
}
s1 = s;
}
if (found) {
path.push_back(beginWord);
dfs(beginWord, endWord);
}
return ans;
}
void dfs(string word, string endWord) {
if (word == endWord) {
ans.push_back(path);
return;
}
for (string child: children[word]) {
path.push_back(child);
dfs(child, endWord);
path.pop_back();
}
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# 0127. 单词接龙 (opens new window)
题目
字典 wordList 中从单词 beginWord 和 endWord 的 转换序列 是一个按下述规格形成的序列 beginWord -> s1 -> s2 -> ... -> sk:
- 每一对相邻的单词只差一个字母。
- 对于 1 <= i <= k 时,每个 si 都在 wordList 中。注意, beginWord 不需要在 wordList 中。
- sk == endWord
给你两个单词 beginWord 和 endWord 和一个字典 wordList ,返回 从 beginWord 到 endWord 的 最短转换序列 中的 单词数目 。如果不存在这样的转换序列,返回 0 。
从 beginWord 和 endWord 进行双向 BFS,相遇时返回扩展步数即可。
代码
class Solution {
public:
int ladderLength(string beginWord, string endWord, vector<string>& wordList) {
unordered_set<string> dict(wordList.begin(), wordList.end());
if (!dict.count(endWord)) return 0;
unordered_set<string> s1{beginWord}, s2{endWord};
int step = 1;
while (!s1.empty() && !s2.empty()) {
step++;
if (s1.size() > s2.size()) swap(s1, s2);
for (string w: s1) dict.erase(w);
for (string w: s2) dict.erase(w);
unordered_set<string> s;
for (string word: s1) {
for (int i = 0; i < word.length(); i++) {
char ch = word[i];
for (char j = 'a'; j <= 'z'; j++) {
word[i] = j;
if (s2.count(word)) return step;
if (!dict.count(word)) continue;
s.insert(word);
}
word[i] = ch;
}
}
s1 = s;
}
return 0;
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# 0310. 最小高度树 (opens new window)
题目
解析
代码