題目描述
給定兩個單詞(beginWord 和 endWord)和一個字典,找到從 beginWord 到 endWord 的最短轉換序列的長度。轉換需遵循如下規則:
每次轉換隻能改變一個字母。
轉換過程中的中間單詞必須是字典中的單詞。
說明:
如果不存在這樣的轉換序列,返回 0。
所有單詞具有相同的長度。
所有單詞只由小寫字母組成。
字典中不存在重複的單詞。
你可以假設 beginWord 和 endWord 是非空的,且二者不相同。
示例 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" 不在字典中,所以無法進行轉換。
來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/word-ladder
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。
白話題目:
算法:
詳細解釋關注 B站 【C語言全代碼】學渣帶你刷Leetcode 不走丟 https://www.bilibili.com/video/BV1C7411y7gB
C語言完全代碼
#define MAX_QUEUE_SIZE 10000
bool visited[MAX_QUEUE_SIZE] = {false};
typedef struct node {
char *word;
int level;
} Node;
typedef struct Que {
Node data[MAX_QUEUE_SIZE];
int head;
int tail;
int qsize;
} QueUe;
void InitQue(QueUe *que)
{
que->head = -1;
que->tail = -1;
que->qsize = 0;
memset(que->data, 0, sizeof(Node) * MAX_QUEUE_SIZE);
}
void Inque(QueUe *que, char *word, int idx)
{
if (que->qsize == MAX_QUEUE_SIZE) {
return ;
}
que->tail = (que->tail + 1) % MAX_QUEUE_SIZE;
que->data[que->tail].word = word;
que->data[que->tail].level = idx;
(que->qsize)++;
}
Node *Outque(QueUe *que)
{
if (que->qsize == 0) { // 出隊時先判斷隊列是否空
return NULL;
}
que->head = (que->head + 1) % MAX_QUEUE_SIZE;
(que->qsize)--;
Node *temp = &(que->data[que->head]);
return temp;
}
int QueSize(QueUe *que)
{
return que->qsize;
}
bool is_empty(QueUe *que) {
if (que->qsize == 0) {
return true;
}
return false;
}
QueUe g_que;
bool ifFindDifWord(char *srcWord, char *destWord)
{
int i;
bool ismatched = false;
int wordLen = strlen(srcWord);
for (i = 0; i < wordLen; i++) {
if (srcWord[i] != destWord[i]) {
if (ismatched) { // 如果兩個單詞中有兩個字母不一樣,則單詞不滿足只有一個字母不一樣的要求,返回false
return false;
}
ismatched = true;
}
}
return ismatched;
}
// 將wordlist裏與node->word 只有一個字母之差的單詞如隊列
int WordNeighborInQue(QueUe *que, Node *node, char *endWord, char **wordList, int wordListSize)
{
int i;
bool ifDiffWord = false;
char *srcWord = node->word;
int srclevel = node->level;
for (i = 0; i < wordListSize; i++) {
if (visited[i] == true) {
continue;
}
ifDiffWord = ifFindDifWord(srcWord, wordList[i]);
if (ifDiffWord == true) {
if (strcmp(endWord, wordList[i]) == 0) {
return srclevel + 1;
}
Inque(que, wordList[i], srclevel + 1);
visited[i] = true;
}
}
return 0; // 表示node->word的鄰居都不是目的單詞
}
int GetLength(QueUe *que, char * beginWord, char * endWord, char ** wordList, int wordListSize, int beginWordIdx)
{
// 將visited【beginwordIdx】置1
if (beginWordIdx != -1) {
visited[beginWordIdx] = true;
}
Inque(que, beginWord, 1);
//遍歷beginword單詞的所有鄰居,加入隊列裏
int ret = 0;
int curQueSize = 0;
Node *strTemp;
while(is_empty(que) != true) {
curQueSize = que->qsize;
while(curQueSize != 0) {
strTemp = Outque(que);
ret = WordNeighborInQue(que, strTemp, endWord, wordList, wordListSize);
// ret != 0 說明已經變換到目的串
if (ret != 0) {
return ret;
}
curQueSize--;
}
}
return 0;
}
int ladderLength(char * beginWord, char * endWord, char ** wordList, int wordListSize)
{
if (wordList == NULL) {
return 0;
}
int i;
int ret;
for (i = 0; i < wordListSize; i++) {
ret = strcmp(wordList[i], endWord);
if (ret == 0) {
break;
}
}
if (i == wordListSize) { // 字典中不存在endword
return 0;
}
int beginWordIdx = -1;
for (i = 0; i < wordListSize; i++) {
ret = strcmp(wordList[i], beginWord);
if (ret == 0) {
break;
}
}
if (i != wordListSize) { // 字典中存在beginword
beginWordIdx = i;
}
memset(visited, false, sizeof(bool) * MAX_QUEUE_SIZE);
InitQue(&g_que);
return GetLength(&g_que, beginWord, endWord, wordList, wordListSize, beginWordIdx);
}