Сложность: hard
Найдите все кратчайшие пути преобразования от beginWord до endWord, изменяя по одной букве за раз, так чтобы каждое промежуточное слово было из wordList.
Пример:
Input: beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log","cog"]
Output: [["hit","hot","dot","dog","cog"],["hit","hot","lot","log","cog"]]
👨💻 Алгоритм:
1⃣Используем BFS, чтобы построить граф уровней (adjList) от beginWord до всех достижимых слов. Каждое слово связано с соседними словами, отличающимися на одну букву.
2⃣Удаляем слова из wordList после каждого уровня, чтобы избежать повторных посещений и гарантировать, что пути будут минимальной длины.
3⃣После BFS используем обратный backtracking от endWord к beginWord, используя построенный adjList, чтобы восстановить все возможные кратчайшие пути.
😎 Решение:
class Solution {
public:
unordered_map<string, vector<string>> adjList;
vector<string> currPath;
vector<vector<string>> shortestPaths;
vector<string> findNeighbors(string &word, unordered_set<string> &wordList) {
vector<string> neighbors;
for (int i = 0; i < word.size(); i++) {
char oldChar = word[i];
for (char c = 'a'; c <= 'z'; c++) {
if (c != oldChar) {
word[i] = c;
if (wordList.count(word)) neighbors.push_back(word);
}
}
word[i] = oldChar;
}
return neighbors;
}
void backtrack(string &source, string &destination) {
if (source == destination) {
shortestPaths.push_back(vector<string>(currPath.rbegin(), currPath.rend()));
return;
}
for (string& neighbor : adjList[source]) {
currPath.push_back(neighbor);
backtrack(neighbor, destination);
currPath.pop_back();
}
}
void bfs(string &beginWord, unordered_set<string> &wordList) {
queue<string> q;
q.push(beginWord);
unordered_set<string> visited;
visited.insert(beginWord);
while (!q.empty()) {
int size = q.size();
unordered_set<string> thisLevelVisited;
for (int i = 0; i < size; i++) {
string currWord = q.front();
q.pop();
vector<string> neighbors = findNeighbors(currWord, wordList);
for (string& neighbor : neighbors) {
if (!visited.count(neighbor)) {
if (!thisLevelVisited.count(neighbor)) {
q.push(neighbor);
thisLevelVisited.insert(neighbor);
}
adjList[neighbor].push_back(currWord);
}
}
}
for (const string& word : thisLevelVisited) {
wordList.erase(word);
visited.insert(word);
}
}
}
vector<vector<string>> findLadders(string beginWord, string endWord, vector<string> &wordList) {
unordered_set<string> wordSet(wordList.begin(), wordList.end());
if (!wordSet.count(endWord)) return {};
bfs(beginWord, wordSet);
currPath = {endWord};
backtrack(endWord, beginWord);
return shortestPaths;
}
};Ставь 👍 и забирай 📚 Базу знаний