127. ワードラダー
辞書 wordList を使用した単語 beginWord から単語 endWord への変換シーケンスは、次のような単語 beginWord -> s1 -> s2 -> … -> sk のシーケンスになります。
- 隣接する単語のペアはすべて 1 文字ずつ異なります。
- 1 <= i <= k のすべての si は wordList にあります。beginWord は wordList にある必要はないことに注意してください。
- sk == エンドワード
beginWord と endWord の 2 つの単語と辞書の wordList を指定すると、beginWord から endWord までの最短の変換シーケンス内の単語の数を返します。そのようなシーケンスが存在しない場合は 0 を返します。
例 1:
入力: beginWord = "hit"、endWord = "cog"、wordList = ["hot","dot","dog","lot","log","cog"] 出力: 5 説明: 1 つの
最短の
変換シーケンス「hit」→「hot」→「dot」→「dog」→「cog」で、5 単語の長さになります。
例 2:
入力: beginWord = "hit"、endWord = "cog"、wordList = ["hot","dot","dog","lot","log"] 出力: 0 説明: endWord "cog" が
ありませ
ん。 wordList であるため、有効な変換シーケンスはありません。
制約:
- 1 <= beginWord.length <= 10
- endWord.length == beginWord.length
- 1 <= wordList.length <= 5000
- wordList[i].length == beginWord.length
- beginWord、endWord、wordList[i] は英小文字で構成されます。
- beginWord != endWord
- wordList 内のすべての単語は一意です。
From: LeetCode
Link: 127. ワードラダー
解決:
アイデア:
- beginWord「ヒット」およびレベル 1 から始めます。
- キュー = [「ヒット」]
- 「ヒット」をキューから取り出し、その近隣を探索します。
- wordList 内の各単語をチェックして、「ヒット」の近傍 (1 文字違いで未訪問の単語) を見つけます。
- 「熱い」は隣人です。「ホット」を訪問済みとしてマークし、キューに追加します。
- キュー = [「ホット」]
- レベルを2に上げます。
- 「ホット」をキューから取り出し、その近隣を探索します。
- 「hot」の近傍 (wordList 内の 1 文字異なる未訪問の単語) を検索します。
- 「ドット」と「ロット」は隣接しています。それらを訪問済みとしてマークし、キューに追加します。
- キュー = [“ドット”, “ロット”]
- レベルを3に上げます。
- 「ドット」をキューから取り出し、その近隣を探索します。
- 「ドット」の近傍を見つけます。
- 「犬」は隣人です。「犬」を訪問済みとしてマークし、キューに追加します。
- キュー = [“ロット”, “犬”]
- 「lot」をデキューし、その近隣を探索します。
- 「ロット」の隣人を見つけます。
- 「log」は隣人です。「ログ」を訪問済みとしてマークし、キューに追加します。
- キュー = [“犬”, “ログ”]
- レベルを4に上げます。
- 「犬」をキューから取り出し、その近隣を探索します。
- 「犬」の隣人を探します。
- 「歯車」は隣人です。「cog」を訪問済みとしてマークし、キューに追加します。
- キュー = [“ログ”, “歯車”]
- 「ログ」をキューから取り出し、その近隣を探索します。
- 「丸太」の近傍を検索します。
- 未訪問の隣人はいません。
- 尾 = [「歯車」]
- 「cog」をキューから取り出し、その近隣を探索します。
- 「cog」はエンドワードです。
- 返されるレベルは 5 で、最短の変換シーケンス: 「hit」 -> 「hot」 -> 「dot」 -> 「dog」 -> 「cog」 を表します。
コード:
bool isOneLetterDiff(char *a, char *b) {
int diffCount = 0;
while (*a) {
if (*(a++) != *(b++)) diffCount++;
if (diffCount > 1) return false;
}
return diffCount == 1;
}
int ladderLength(char *beginWord, char *endWord, char **wordList, int wordListSize) {
if (!beginWord || !endWord || !wordList || wordListSize == 0) return 0;
bool *visited = (bool *)calloc(wordListSize, sizeof(bool));
char **queue = (char **)malloc(sizeof(char *) * (wordListSize + 1));
int front = 0, rear = 0;
queue[rear++] = beginWord;
int level = 1;
while (front < rear) {
int size = rear - front;
for (int i = 0; i < size; i++) {
char *word = queue[front++];
if (strcmp(word, endWord) == 0) {
free(visited);
free(queue);
return level;
}
for (int j = 0; j < wordListSize; j++) {
if (!visited[j] && isOneLetterDiff(word, wordList[j])) {
visited[j] = true;
queue[rear++] = wordList[j];
}
}
}
level++;
}
free(visited);
free(queue);
return 0;
}