127. 单词接龙-中等-图、BFS、字符串
给定两个单词(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" 不在字典中,所以无法进行转换。
题解
与昨天题目正相反,即便看完答案也觉得,这尼玛是中等题?
不过认真地思考和复盘还是需要的。
思路:根据单词与单词之间的转换,可以隐隐约约感觉到,这是一道关于图
的问题。每次变化的种类多,所以是一道BFS
的问题。
此题的难点有两个:
- 首先是图的表示,官网的答案建立了图,而另一个比较好题解则只是用到了图的思想,但没有将图建立。所以在此题中,
图
的思想是一个值得思考的点。 - 第二个难点我觉得就是
BFS
,感觉需要考究的细节有很多,不常用的话很容易忽略这些。 - 单词的变化感觉也不是很简单,可以单出一道题了,需要将
String
类型转换为char[]
数组形式,再对每个字符进行变化。(注意保存变化之前的字符,还要还原呢)
第二次做的话尝试独自思考双BFS
的方法吧
class Solution {
Set<String> wordSet;
Set<String> visited;
Queue<String> queue;
public int ladderLength(String beginWord, String endWord, List<String> wordList) {
// 此题没有建立图,却是一道关于图的题,思想也是图的思想
// 首先把数据存入哈希表中,
wordSet = new HashSet<>(wordList);
visited = new HashSet<>(); // 把遍历过的数据放入visited里
visited.add(beginWord);
if( wordSet.size() == 0 || !wordSet.contains(endWord)){
return 0;
}
wordList.remove(beginWord);
// BFS就需要用到队列了
queue = new LinkedList<>();
int step = 1;
queue.offer(beginWord);
while(!queue.isEmpty()){
// 需要用qsize记录queue,不能在for里面直接调用size()函数,每次queue的size都不一样
int qsize = queue.size();
// 需要用for在进行二次遍历
for(int i=0; i<qsize; i++){
String word = queue.poll();
if(wordDetect(word, endWord)){
return step + 1;
}
}
step++;
}
return 0;
}
public boolean wordDetect(String word, String endWord){
// 如何更改字符串的每个字母也是本题的难点之一
char[] charWord = word.toCharArray();
for(int i=0; i<charWord.length; i++ ){
char originChar = charWord[i];
for(char c ='a'; c <= 'z';c++){
if(c == originChar){
continue;
}
charWord[i] = c;
String newWord = new String(charWord);
// 在set里面存在,且没有遍历过,直接放入队列里面
if(wordSet.contains(newWord) && !visited.contains(newWord)){
if(newWord.equals(endWord)){
return true;
}else{
visited.add(newWord);
queue.add(newWord);
}
}
}
charWord[i] = originChar;
}
return false;
}
}