在字典(单词列表) wordList 中,从单词 beginWord 和 endWord 的 转换序列 是一个按下述规格形成的序列:
序列中第一个单词是 beginWord 。
序列中最后一个单词是 endWord 。
每次转换只能改变一个字母。
转换过程中的中间单词必须是字典 wordList 中的单词。
给定两个长度相同但内容不同的单词 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。
这里使用的是BFS(这种方式其实不够高效,但是我觉得最好理解)
具体的思路:首先先决条件无非就是判断wordList 是否含有endWord ,没有的话可以直接返回了。
然后就是判断endWord 和beginWord 是否相同,相同的话皆大欢喜。
下来就是建立一个队列,一般BFS的做法都是使用队列来实现,将beginWord 存放的队列中,同时,再创建一个set集合用于记录单词是否已经入队。
然后每次将这一层的单词取出来,查找他的nextWord集合,判断集合中元素是否满足等于endWord,满足即可返回结果,否则将这个集合放在下一层中。
public int ladderLength(String beginWord, String endWord, List<String> wordList) {
if (beginWord.equals(endWord)) return 0;
Set<String> set = new HashSet<>(wordList);
Queue<String> queue = new LinkedList<>();
if (!set.contains(endWord)) return 0;
Set<String> visit = new HashSet<>();
queue.offer(beginWord);
visit.add(beginWord);
int step = 1;
while (!queue.isEmpty()) {
int size = queue.size();
for (int i = 0; i < size; i++) {
String str = queue.poll();
for (String nextWord : next(str, wordList, visit)) {
if (nextWord.equals(endWord)) return step + 1;
visit.add(nextWord);
queue.offer(nextWord);
}
}
step++;
}
return 0;
}
public List<String> next(String str, List<String> wordList, Set<String> visit) {
List<String> list = new ArrayList<>();
for (String word : wordList) {
if (!visit.contains(word) && isNext(str, word)) {
list.add(word);
}
}
return list;
}
public boolean isNext(String str1, String str2) {
if (str1.length() != str2.length()) return false;
int count = 0;
for (int i = 0; i < str1.length(); i++) {
if (str1.charAt(i) != str2.charAt(i)) {
count++;
}
if (count > 1) return false;
}
return count <= 1;
}