困难题
一开始是超时,后来一步步优化从 600ms 到了 343ms
最开始的想法:用HashMap存储每一个单词相对应可以转换成的单词,然后通过BFS的思想寻找解
显然为了避免重复路径,我们需要一个集合来记录已经使用过的单词,这里我直接把wordlist的中的单词删去达到标记的效果。
优化最大的地方在于寻找每一个单词相对应可以转换成的单词时,我采取遍历判断有几个字母不同,当有两个不同时就退出循环(虽然只是一个很简单的优化,但可以省很多时间,因为这个步骤是最里面的一重循环,任何优化都将被放大)
看了题解之后学习到的两个优化点
1.双端BFS:
显然如果endWord的临近点少于beginWord的临界点,那么从endWord开始BFS更快。所以我们每次都选取点集合较少的那一端进行BFS。
2.临近点查找方式:
首先将所有的字符存到结构为HashSet的dic字典里去,然后将字符串的每一位挨个从a变到z,
在变化的时候实时去字典里查,因为是hashset,所以复杂度是O(1),非常快。
如果查到了,则就是找到了临近点。
自己的(343ms)
class Solution {
public int ladderLength(String beginWord, String endWord, List<String> wordList) {
List<String> m = new ArrayList<>();
m.add(beginWord);
wordList.remove(beginWord);
for(int i = 2;m.size() > 0;i ++){
int p = m.size();
for(int j = 0; j < p; j++){
String t = m.get(0);
for(int k = 0; k < wordList.size(); k++){
String s = wordList.get(k);
int jud = 0;
for(int q = 0; q < s.length(); q++){
if(s.charAt(q) != t.charAt(q))
jud++;
if(jud > 1)
break;
}
if(jud == 1){
if(s.compareTo(endWord) == 0)
return i;
m.add(s);
wordList.remove(s);
k--;
}
}
m.remove(0);
}
}
return 0;
}
}
题解(10ms)
class Solution {
public int ladderLength(String beginWord, String endWord, List<String> wordList) {
Set<String>words=new HashSet<>(wordList);
if(!words.contains(endWord)) return 0;
Set<String>visited=new HashSet<>();
visited.add(beginWord);
Set<String>beginVisited=new HashSet<>();
beginVisited.add(beginWord);
Set<String>endVisited=new HashSet<>();
endVisited.add(endWord);
int step=1;
while (!beginVisited.isEmpty()&&!endVisited.isEmpty()){
if(beginVisited.size()>endVisited.size()){
Set<String>temp=beginVisited;
beginVisited=endVisited;
endVisited=temp;
}
Set<String>nextLevelVisited=new HashSet<>();
for (String str:beginVisited){
if(isVisited(words,visited,endVisited,nextLevelVisited,str)){
return step+1;
}
}
beginVisited=nextLevelVisited;
step++;
}
return 0;
}
public boolean isVisited(Set<String>words,Set<String>visited,Set<String>endVisited,Set<String>nextLevelVisited,String cur){
char []chars=cur.toCharArray();
for (int i=0;i<cur.length();i++){
char orignal=chars[i];
for (char j='a';j<='z';j++){
if(j==orignal)continue;
chars[i]=j;
String temp=new String(chars);
if(words.contains(temp)){
if(endVisited.contains(temp)){
return true;
}
if(!visited.contains(temp)){
nextLevelVisited.add(temp);
visited.add(temp);
}
}
}
chars[i]=orignal;
}
return false;
}
}