题目
给出两个单词(beginWord 和 endWord)和一个字典,找到从 beginWord 到 endWord 的最短转换序列,转换需遵循如下规则:
- 每次只能改变一个字母。
- 变换过程中的中间单词必须在字典中出现。
例如,给出:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log","cog"]
一个最短的变换序列是: "hit" -> "hot" -> "dot" -> "dog" -> "cog"
,
返回长度 5
。
注意:
- 如果没有这样的转换序列,则返回0。
- 所有单词具有相同的长度。
- 所有单词只包含小写字母字符。
- 您可能会认为单词列表中没有重复项。
- 你可能会认为 beginWord 和 endWord 是非空的并且不一样。
更新 (2017/1/20):
wordList 参数已被更改为字符串列表(而不是一组字符串)。请重新加载代码定义以获取最新更改。
分析
广度优先的题, 在网上看着解题报告做的,一开始想着用递归,将所有的情况都列举出来,时间复杂度会很高,而且自己也没有写完。。。。。
还有就是判断两个单词是否是相邻的(比如 dog 和 dug),不要挨个去比较,因为也会超时,wordList里单词少还可以,如果数量一多,那么就会多出去很多次比较,导致超时;
不去挨个比较那么就让要比较的单词word挨个换字母,去判断wordList中是否存在差了一个字母后的word。 嗯。。。。就比如:
wordList= hot dog dot …… 我现在要比较 hit 在wordList中是否存在相邻的单词:
首先,将 hit 的第一个字母 h 用a——z替换,:ait bit cit dit fit ……xit yit zit 在替换的同时 ,看一下 wordList中 是否存在 ait bit cit dit fit ……xit yit zit ,
我们可以发现 hot 就符合 然后就可以将 hot 加入到我们的temp集合中去,继续看下面是否还有相邻的单词 ;
替换第二个字母 o :hat hbt hct hdt…… hxt hyt hzt;
第三个字母 t : hoa hob hoc …… hox hoy hoz;
这样比较的话,就不会超时了。
嗯。。。还有个小问题 题中的wordList是有重复元素的,把它放到set中去就可以去重复元素啦。
代码
class Solution {
public int ladderLength(String beginWord, String endWord, List<String> wordList) {
if ((beginWord == null || endWord == null) || beginWord.equals(endWord))
return 0;
int count = 0;
//解决重复单词问题
Set<String> list = new HashSet<>(wordList);
Set<String> set = new HashSet<>();
set.add(beginWord);
while (!set.contains(endWord)){
Set<String> temp = new HashSet<>();
for (String str : set){
for (int i = 0; i < str.length(); i++) {
char[] chars = str.toCharArray();
for (int j = 97; j < 97+26; j++) {//将set中的单词字母每个替换一遍
chars[i] = (char)j;
String word = new String(chars);
if (list.contains(word)){//list中是否存在和set单词中相差一个字母的单词
list.remove(word);//存在删掉word
temp.add(word);
}
}
}
}
if (temp.size() == 0)
return 0;
count++;
set = temp;
}
return count+1;
}
}