先用bfs,建立单词之间的连接,一个是distance的map,存的是从start开始(start的distance为0),然后到词典中与他有一个字母不一样的单词,distance +1,以此类推,可以简单的理解用distance量化了 bfs 逐层遍历的层数。另一个map用来储存当前节点和他的邻居节点,邻居节点存在 map value的list里。邻居节点是所有和他只有一个字母不一样的单词,注意存的时候,按照pop出来的单词,找到所有和他只差一个单词不一样的list,把pop出来的单词分别加到这个list中的单词在map中key对应的list里。然后这个list里,把此时还不在distance 里的单词加进去,并且距离比pop出来的那个大一,因为这个单词其实就是在pop出来的单词的下一层了。
DFS:这里dfs也应用了回溯法,具体的就是,从end往前找,先把end加到path里,如果刚加到path的这个单词 等于start,那么就把path反过来,然后加到res里,再反过来(因为要回溯删掉最后一个加进去的单词,回到上层 继续遍历),如果这个单词不是start,那么就把这个单词 cur 在map中对应的list(他的邻居)取出来,并对这些邻居进行遍历,遍历时要判断他是不是在distance中存在,如果存在的话,是不是对应的距离比cur的距离小1,因为只有小1,才能保证他是在cur的上一层,这样可以去除不是最小的路径。 经过这个判断,然后对当前遍历的这个单词进行dfs递归调用。
class Solution {
public List<List<String>> findLadders(String start, String end, List<String> wordList) {
List<List<String>> res = new ArrayList<List<String>>();
Set<String> dict = new HashSet<>();
for(String word: wordList){
dict.add(word);
}
if(start.compareTo(end) == 0) return res;
Set<String> visited = new HashSet<String>();
Set<String> cur = new HashSet<String>();
HashMap<String, ArrayList<String>> graph = new HashMap<String, ArrayList<String>>();
graph.put(end,new ArrayList<String>());
cur.add(start);
boolean found = false;
while (cur.isEmpty() == false && found == false) {
Set<String> queue = new HashSet<String>();
for(Iterator<String> it=cur.iterator();it.hasNext();) {
visited.add(it.next());
}
for(Iterator<String> it=cur.iterator();it.hasNext();) {
String str = it.next();
char[] word = str.toCharArray();
for (int j = 0; j < word.length; ++j) {
char before = word[j];
for (char ch = 'a'; ch <= 'z'; ++ch) {
if (ch == before) continue;
word[j] = ch;
String temp = new String(word);
if (dict.contains(temp) == false) continue;
if (found == true && end.compareTo(temp) != 0) continue;
if (end.compareTo(temp) == 0) {
found = true;
(graph.get(end)).add(str);
continue;
}
if (visited.contains(temp) == false) {
queue.add(temp);
if (graph.containsKey(temp) == false) {
ArrayList<String> l = new ArrayList<String>();
l.add(str);
graph.put(temp,l);
} else {
(graph.get(temp)).add(str);
}
}
}
word[j] = before;
}
}
cur = queue;
}
if (found == true) {
ArrayList<String> path = new ArrayList<String>();
trace(res, graph, path, start, end);
}
return res;
}
public void trace(List<List<String>> res,
HashMap<String, ArrayList<String>> graph,
ArrayList<String> path,
String start, String now) {
path.add(now);
if (now.compareTo(start) == 0) {
ArrayList<String> ans = new ArrayList<String>(path);
Collections.reverse(ans);
res.add(ans);
path.remove(path.size()-1);
return;
}
ArrayList<String> cur = graph.get(now);
for (int i = 0; i < cur.size(); ++i) {
trace(res,graph,path,start,cur.get(i));
}
path.remove(path.size()-1);
}
}