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:
- Only one letter can be changed at a time.
- Each transformed word must exist in the word list. Note that beginWord is not a transformed word.
Note:
- Return 0 if there is no such transformation sequence.
- All words have the same length.
- All words contain only lowercase alphabetic characters.
- You may assume no duplicates in the word list.
- You may assume beginWord and endWord are non-empty and are not the same.
one set [visited] record visited words in last layer, one set [current] record words in the current layer, one set [dict] record words in dict(candidates for the ladder)
change each letter of the words in [visited] to see whether dict contains the new word, if yes, remove the word from dict, and add it to [current].
visited=current
if current.isEmpty(), return 0;
class Solution { public int ladderLength(String beginWord, String endWord, List<String> wordList) { Set<String> visited=new HashSet<>(); visited.add(beginWord); Set<String> dict=new HashSet<>(wordList); int len=1; while(!dict.isEmpty()){ Set<String> current=new HashSet<>(); for(String str:visited){ char[] ch=str.toCharArray(); for(int i=0;i<ch.length;i++){ char c=ch[i]; for(char l='a';l<='z';l++){ if(c==l) continue; ch[i]=l; if(endWord.equals(String.valueOf(ch))){ return len+1; } if(dict.contains(String.valueOf(ch))){ dict.remove(String.valueOf(ch)); current.add(String.valueOf(ch)); } } ch[i]=c; } } if(current.isEmpty()) return 0; visited=current; len++; } return 0; } }
注意:
不要把待比对对象和dict中的每个单词依次比较是否只变了一个字母,这样当dict单词数目巨大时时间复杂度太高,会tle。应该对待比对对象的每个字母依次替换'a'-'z'来看是否有相应的单词在dict中,这样时间复杂度是(26*word.length())。需要小心的是,把每个字母换掉后还需要换回来,不要忘了换回来这个步骤。
改进:
two end bfs
从两端分别开始搜索,思路完全同上,只是两边向中间搜索能大大加快。分别设置两个set,一个从start开始bfs,一个从end开始,每次从layer少的那一侧开始延展,看延展一步是否能连接上另一侧,如果可以,则找到了一条最短路径。
class Solution { public int ladderLength(String beginWord, String endWord, List<String> wordList) { Set<String> start=new HashSet<>(); Set<String> end=new HashSet<>(); Set<String> dict=new HashSet<>(wordList); if(!dict.contains(endWord)) return 0; start.add(beginWord); end.add(endWord); dict.remove(endWord); int len=2; while(!start.isEmpty()){ if(start.size()>end.size()){ Set<String> temp=start; start=end; end=temp; }//每次出发从小的去找大的 Set<String> current=new HashSet<>(); for(String str:start){ char[] chars=str.toCharArray(); for(int i=0;i<chars.length;i++){ char c=chars[i]; for(char l='a';l<='z';l++){ if(chars[i]==l) continue; chars[i]=l; String word=new String(chars); if(end.contains(word)) return len; if(dict.contains(word)){ current.add(word); dict.remove(word); } } chars[i]=c; } } start=current; len++; } return 0; } }
注意,add一个相应的就要remove一个,这道题代码相对比较长,细节的地方容易出现笔误或者漏掉,一定要小心,理清楚逻辑再写,每一步都要想清楚,不要掉了步骤。
浙公网安备 33010602011771号