问题:算法
Given two words (beginWord and endWord), and a dictionary's word list, find the length of shortest transformation sequence from beginWord to endWord, such that:优化
For example,spa
Given:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log","cog"]
code
As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog"
,
return its length 5
.orm
Note:ci
UPDATE (2017/1/20):
The wordList parameter had been changed to a list of strings (instead of a set of strings). Please reload the code definition to get the latest changes.rem
解决:字符串
【题意】和当前单词相邻的单词是:对当前单词改变一个字母且在字典中存在的单词。get
① 这个就是图论算法中的单源最短路, 求单源最短路比较通用的算法是BFS和Dijkstra, 其区别是BFS不能用于带权重的图中, 然后者能够, 能够看出在本题中两个字符串之间是无权重的, 也就是若是连通就是1, 不联通就是无穷. BFS和Dijkstra的区别是前者的时间复杂度是O(n), 后者最多优化到O(m log n), 因此若是条件成立通常选择BFS要更好.string
以题目中的例子为例:
level = 1 hit dict = [hot, dot, dog, lot, log,cog]
ait bit cit ... xit yit zit , hat hbt hct ... hot ... hxt hyt hzt , hia hib hic ... hix hiy hiz
level = 2 hot dict = [dot, dog, lot, log,cog]
aot bot cot dot ... lot ... xot yot zot,hat hbt hct ... hxt hyt hzt,hoa hob hoc ... hox hoy hoz
level = 3 dot lot dict = [dog,log,cog]
aot bot ... yot zot,dat dbt ...dyt dzt,doa dob ... dog .. doy doz,
aot bot ... yot zot,lat lbt ... lyt lzt,loa lob ... log... loy loz
level = 4 dog log dict = [cog]
aog bog cog
level = 5 cog dict = []
class Solution {//99ms
public int ladderLength(String beginWord, String endWord, List<String> wordList) {
if(beginWord == null || endWord == null || beginWord.length() == 0 || endWord.length() == 0){
return 0;
}
Set<String> set = new HashSet<>(wordList);//去重,而且去除了beginWord相同的单词。
if(set.contains(beginWord)){
set.remove(beginWord);
}
Queue<String> queue = new LinkedList<>();
int level = 1;
int curnum = 1; //当前层待处理的节点数
int nextnum = 0;//记录下一层节点数
queue.offer(beginWord);
while(! queue.isEmpty()){
String word = queue.poll();
curnum --;
for (int i = 0;i < word.length() ;i ++ ) {//更换单词
char[] wchar = word.toCharArray();
for (char j = 'a';j <= 'z' ;j ++ ) {
wchar[i] = j;
String tmp = new String(wchar);
if(set.contains(tmp)){
if(tmp.equals(endWord)){
return level + 1;
}
nextnum ++;
queue.add(tmp);
set.remove(tmp);//要将遍历到的单词从字典中删除
}
}
}
if(curnum == 0){
curnum = nextnum;
nextnum = 0;
level ++;
}
}
return 0;
}
}
② 对上面的方法进行优化,若是咱们从两头扫,扫到中间任何一个word可以串联起来均可以,若是没有找到能够串联的word,那么返回0。
class Solution {//23ms
public int ladderLength(String beginWord, String endWord, List<String> wordList){
if (wordList == null || wordList.size() == 0){
return 0;
}
Set<String> set = new HashSet<>(wordList);
if (! set.contains(endWord)) return 0;//【注意】endWord是在字典里的,两端查找须要额外判断
if (beginWord.equals(endWord)) return 1;
Set<String> beginSet = new HashSet<>();
Set<String> endSet = new HashSet<>();
beginSet.add(beginWord);
set.remove(beginWord);
endSet.add(endWord);
set.remove(endWord);
return twoEndBFS(beginSet,endSet,set,2);
}
public int twoEndBFS(Set<String> beginSet,Set<String> endSet,Set<String> set,int level){
if (beginSet.isEmpty() || endSet.isEmpty()) return 0;
if (beginSet.size() > endSet.size()) return twoEndBFS(endSet,beginSet,set,level);
Set<String> tmp = new HashSet<>();//做为从当前层开始的beginSet
for (String word : beginSet){
char[] wchar = word.toCharArray();
for (int i = 0;i < wchar.length;i ++){
char c = wchar[i];
for (char j = 'a';j <= 'z';j ++){
wchar[i] = j;
String newWord = new String(wchar);
if (endSet.contains(newWord)) return level;//能够接上
if (set.contains(newWord)){
set.remove(newWord);
tmp.add(newWord);
}
}
wchar[i] = c;
}
}
return twoEndBFS(tmp,endSet,set,level + 1); } }