距离上一次刷题已经过去了.........嗯............我数一一下............整整十天,今天再来解一道算法题
由于这段时间准备简历,没咋写博客。。今天回来了!!!!!!!!!!!!!!!!
话不多说,看题:
题目:
字典 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
中的所有字符串 互不相同
嘶。。。。太难了,不会。。。。
猝!!!!!
正片开始:
解题思路:
这道题可以使用广度优先搜索(BFS)算法来解决。BFS 算法从 beginWord
开始,逐层向外扩展,直到找到 endWord
。以下是如何使用 BFS 算法解决这道题的思路:
- 使用队列
queue
来存储待访问的单词。 - 使用集合
visited
来记录已访问过的单词,避免重复访问。 - 初始化层数
level
为 1。 - 将
beginWord
加入队列queue
,并将beginWord
加入集合visited
。 - 循环执行以下步骤,直到队列
queue
为空:- 将队列
queue
中的所有单词出队。 - 对于每个出队的单词
currentWord
:- 如果
currentWord
等于endWord
,则找到最短转换序列,返回层数level
。 - 否则,获取
currentWord
的所有相邻单词neighbors
。 - 对于每个相邻单词
neighbor
:- 如果
neighbor
未被访问过,则将其加入队列queue
和集合visited
。
- 如果
- 如果
- 将层数
level
加 1。
- 将队列
- 如果 BFS 结束后仍未找到
endWord
,则返回 0。
具体代码实现:
import java.util.*;
public class WordLadder {
public int ladderLength(String beginWord, String endWord, List<String> wordList) {
// 如果字典中不存在 endWord,则返回 0
if (!wordList.contains(endWord)) {
return 0;
}
// 使用队列进行广度优先搜索(BFS)
Queue<String> queue = new LinkedList<>();
queue.offer(beginWord);
// 使用集合记录已访问过的单词,避免重复访问
Set<String> visited = new HashSet<>();
visited.add(beginWord);
// 层数,从 1 开始
int level = 1;
while (!queue.isEmpty()) {
int size = queue.size();
// 当前层的单词全部出队
for (int i = 0; i < size; i++) {
String currentWord = queue.poll();
// 如果当前单词等于 endWord,则找到最短转换序列,返回层数
if (currentWord.equals(endWord)) {
return level;
}
// 遍历当前单词的相邻单词
List<String> neighbors = getNeighbors(currentWord, wordList);
for (String neighbor : neighbors) {
// 如果相邻单词未被访问过,则将其加入队列和 visited 集合
if (!visited.contains(neighbor)) {
queue.offer(neighbor);
visited.add(neighbor);
}
}
}
// 层数加 1
level++;
}
// 如果 BFS 结束后仍未找到 endWord,则返回 0
return 0;
}
// 获取当前单词的相邻单词
private List<String> getNeighbors(String word, List<String> wordList) {
List<String> neighbors = new ArrayList<>();
for (String candidate : wordList) {
int diffCount = 0;
// 比较两个单词,计算不同字符的数量
for (int i = 0; i < word.length(); i++) {
if (word.charAt(i) != candidate.charAt(i)) {
diffCount++;
}
}
// 如果不同字符的数量为 1,则 candidate 是相邻单词
if (diffCount == 1) {
neighbors.add(candidate);
}
}
return neighbors;
}
}
时间复杂度:
噗噗噗..........
这时间复杂度比我命还长啊。。。。。。。。。。。。。。。。。。。。。
=========================================================================
这道题使用广度优先搜索(BFS)算法,其时间复杂度为 O(V + E),其中:
- V 是单词列表中的单词数量(即顶点数)
- E 是单词列表中单词之间的转换关系数量(即边数)
在最坏的情况下,我们需要遍历整个单词列表,并且每个单词与其他所有单词都存在转换关系。因此,时间复杂度为 O(V^2)。
然而,在实际情况下,单词列表中的单词通常只与少数其他单词存在转换关系。因此,时间复杂度通常会更接近 O(V + E)。
总的来说,这道题的 时间复杂度为 O(V + E),在最坏的情况下为 O(V^2)。
总结
这道题要求找出从一个单词到另一个单词的最短转换序列,转换规则是每次只能改变一个字母,且转换后的单词必须在给定的单词列表中。
我们可以使用广度优先搜索(BFS)算法来解决这道题。BFS 算法从起始单词开始,逐层向外扩展,直到找到目标单词。