力扣第127题 单词接龙 C++ 广度优先搜索 附Java代码
题目
困难
相关标签
字典 wordList
中从单词 beginWord
和 endWord
的 转换序列 是一个按下述规格形成的序列 beginWord -> s1 -> s2 -> ... -> sk
:
- 每一对相邻的单词只差一个字母。
- 对于
1 <= i <= k
时,每个si
都在wordList
中。注意,beginWord
不需要在wordList
中。 sk == endWord
给你两个单词 beginWord
和 endWord
和一个字典 wordList
,返回 从 beginWord
到 endWord
的 最短转换序列 中的 单词数目 。如果不存在这样的转换序列,返回 0
。
示例 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" 不在字典中,所以无法进行转换。
提示:
1 <= beginWord.length <= 10
endWord.length == beginWord.length
1 <= wordList.length <= 5000
wordList[i].length == beginWord.length
beginWord
、endWord
和wordList[i]
由小写英文字母组成beginWord != endWord
wordList
中的所有字符串 互不相同
思路和解题方法
首先,代码将输入的单词列表
wordList
转换为unordered_set
类型的wordSet
,以提高后续的查询速度。接着,代码检查目标单词
endWord
是否在wordSet
中,如果不在则返回0,表示无法完成转换。然后,代码创建了一个
unordered_map
类型的visitMap
,用于记录每个单词是否被访问过以及到达该单词的路径长度。初始化一个队列
que
,并将起始单词beginWord
加入队列。初始化
visitMap
,将起始单词的访问信息插入其中,路径长度初始化为1。进入循环,直到队列为空为止。在循环中,首先取出队列的第一个单词
word
,并移出队列。然后获取到达这个单词的路径长度path
。遍历
word
的每一个字符,对每个字符尝试替换为其他字符(a-z),生成一个新的单词newWord
。对于每个新生成的单词
newWord
,检查是否等于目标单词endWord
,若是,则返回当前路径长度加1,表示找到了最短路径。如果
newWord
在wordSet
中存在并且没有被访问过(即不在visitMap
中),则将其添加到visitMap
中,并将其加入队列,路径长度为当前路径长度加1。最终如果队列为空仍未找到目标单词,则返回0表示无法完成转换。
该算法使用广度优先搜索(BFS)策略,逐层遍历单词的所有可能变换,直到找到目标单词或者遍历完所有可能情况。这样可以保证找到的路径是最短的。
复杂度
时间复杂度:
O(n*L)
时间复杂度取决于单词列表的长度和单词的平均长度。假设单词列表的长度为 n,单词的平均长度为 L,那么算法的时间复杂度大致为 O(n*L)。在最坏情况下,需要遍历整个单词列表,并对每个单词进行 O(L) 的操作。
空间复杂度
O(n*L)
空间复杂度方面,算法使用了一个 unordered_set 存储单词列表,一个 unordered_map 记录访问信息,以及一个队列用于BFS搜索。因此,空间复杂度大致也为 O(n*L),其中 n 为单词列表的长度,L 为单词的平均长度。
c++ 代码
class Solution {
public:
int ladderLength(string beginWord, string endWord, vector<string>& wordList) {
// 将vector转成unordered_set,提高查询速度
unordered_set<string> wordSet(wordList.begin(), wordList.end());
// 如果endWord没有在wordSet出现,直接返回0
if (wordSet.find(endWord) == wordSet.end()) return 0;
// 记录word是否访问过
unordered_map<string, int> visitMap; // <word, 查询到这个word路径长度>
// 初始化队列
queue<string> que;
que.push(beginWord);
// 初始化visitMap
visitMap.insert(pair<string, int>(beginWord, 1));
while(!que.empty()) {
string word = que.front();
que.pop();
int path = visitMap[word]; // 这个word的路径长度
for (int i = 0; i < word.size(); i++) {
string newWord = word; // 用一个新单词替换word,因为每次置换一个字母
for (int j = 0 ; j < 26; j++) {
newWord[i] = j + 'a';
if (newWord == endWord) return path + 1; // 找到了end,返回path+1
// wordSet出现了newWord,并且newWord没有被访问过
if (wordSet.find(newWord) != wordSet.end()
&& visitMap.find(newWord) == visitMap.end()) {
// 添加访问信息
visitMap.insert(pair<string, int>(newWord, path + 1));
que.push(newWord);
}
}
}
}
return 0;
}
};
Java代码
class Solution {
public int ladderLength(String beginWord, String endWord, List<String> wordList) {
// 将单词列表转换为 HashSet 以加快查找速度
HashSet<String> wordSet = new HashSet<>(wordList);
// 特殊情况判断:如果单词集合为空或者不包含目标单词,返回 0
if (wordSet.size() == 0 || !wordSet.contains(endWord)) {
return 0;
}
// 创建 BFS 队列
Queue<String> queue = new LinkedList<>();
queue.offer(beginWord); // 将起始单词加入队列
// 记录单词对应的路径长度
Map<String, Integer> map = new HashMap<>();
map.put(beginWord, 1); // 起始单词路径长度为1
while (!queue.isEmpty()) {
String word = queue.poll(); // 取出队头单词
int path = map.get(word); // 获取到该单词的路径长度
// 遍历单词的每个字符
for (int i = 0; i < word.length(); i++) {
char[] chars = word.toCharArray(); // 将单词转换为字符数组,方便进行替换操作
// 从'a' 到 'z' 遍历替换
for (char k = 'a'; k <= 'z'; k++) {
chars[i] = k; // 替换第i个字符
String newWord = String.valueOf(chars); // 得到新的字符串
// 如果新的字符串值与endWord一致,返回当前路径长度+1
if (newWord.equals(endWord)) {
return path + 1;
}
// 如果新单词在set中,并且没有被访问过
if (wordSet.contains(newWord) && !map.containsKey(newWord)) {
map.put(newWord, path + 1); // 记录单词对应的路径长度
queue.offer(newWord); // 将新单词加入队尾
}
}
}
}
return 0; // 未找到
}
}
觉得有用的话可以点点赞,支持一下。
如果愿意的话关注一下。会对你有更多的帮助。
每天都会不定时更新哦 >人< 。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)