問題:算法
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); } }