127. 单词接龙
给定两个单词(beginWord 和 endWord)和一个字典,找到从 beginWord 到 endWord 的最短转换序列的长度。转换需遵循如下规则:
每次转换只能改变一个字母。
转换过程中的中间单词必须是字典中的单词。
说明:
- 如果不存在这样的转换序列,返回 0。
- 所有单词具有相同的长度。
- 所有单词只由小写字母组成。
- 字典中不存在重复的单词。
- 你可以假设 beginWord 和 endWord 是非空的,且二者不相同。
该题目是NLP相关算法中经常遇到的问题,最短路径问题首先想到的是广度优先搜索,那么就需要将字典中的词汇构建到图结构中,构建图的方法参考了官方虚节点的思路,具体C++代码如下:
class Solution {
public:
unordered_map<string,int> word_id;
vector<vector<int>> edge;
int wordNum=0;//新标准下可以初始化
void addWord(string word)
{
if(!word_id.count(word))
{
word_id[word]=wordNum++;
edge.emplace_back();//在edge中添加一个vector<int>占位
}
}
void addEdge(string word)
{
addWord(word);
int idx1=word_id[word];
for(auto& ch : word)
{
char tmp=ch;
ch='*';
addWord(word);
int idx2=word_id[word];
edge[idx1].push_back(idx2);
edge[idx2].push_back(idx1);
ch=tmp;
}
}
int ladderLength(string beginWord, string endWord, vector<string>& wordList) {
for(auto& word : wordList) addEdge(word);
addEdge(beginWord);
if(!word_id.count(endWord)) return 0;
int beginId=word_id[beginWord];
int endId=word_id[endWord];
vector<int> dis(wordNum,INT_MAX);//储存距离
dis[beginId]=0;
queue<int> my_queue;
my_queue.push(beginId);
while(!my_queue.empty())
{
int currentId=my_queue.front();
my_queue.pop();
if(currentId==endId)
{
return dis[currentId]/2+1;
}
for(auto& id : edge[currentId])
{
if(dis[id]==INT_MAX)
{
dis[id]=dis[currentId]+1;
my_queue.push(id);
}
}
}
return 0;
}
};
运行效果:
来源:力扣(LeetCode)链接:https://leetcode-cn.com/problems/word-ladder