题目描述
给定两个单词(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);
}