问题描述:这里写链接内容
分析:这道题首先要找到最短路径,最短路径是采用BFS方法,之前侯大神给我讲的时候说,为什么BFS找到的节点是最短的,因为BFS搜索过程是类似于波浪型的,一层一层荡出去,这样只要找到了结束点,这个店就一定是最短路径。
但是这道题要求把路径找出来,所以,在BFS过程中还需要记录中间路径,(实际上是构造一棵树),然后在BFS结束之后再进行DFS搜索。这里的一个trick是,在BFS的过程中由后向前找。这样可以避免很多无效的分支。所以需要一个map维护string和它的上一层之间的对应关系。
此外,BFS的搜索过程中并非简单地使用队列的结构,因为每一层与每一层之间要相互隔离,因为很可能上一层之间还有相互指向的支,那么这些支是无效的,应该予以排除。
此外,还要注意什么时候退出循环,当找到end节点之后,并把那一层搜索完之后再退出。
总之这道题很恶心!
代码如下:656ms
public class Solution {
class Node {
String word;
int level;
public Node(String word, int level) {
this.word = word;
this.level = level;
}
}
private String end;
private List<List<String>> res;
private Map<String, List<String>> maps;
public List<List<String>> findLadders(String start, String end,
Set<String> dict) {
res = new ArrayList<>();
// unvisited words set
dict.add(end);
dict.remove(start);
// used to record the map info of <word : the words of next level>
maps = new HashMap<>();
for (String e : dict) {
maps.put(e, new ArrayList<>());
}
// BFS to search from the end to start
Queue<Node> queue = new LinkedList<Node>();
queue.add(new Node(start, 0));
boolean found = false;
int finalLevel = Integer.MAX_VALUE;
int currentLevel = 0;
Set<String> visitedWordsInThisLevel = new HashSet<>();
while (!queue.isEmpty()) {
Node node = queue.poll();
String word = node.word;
int level = node.level;
if (level > finalLevel) {
break;
}
if (level > currentLevel) {
dict.removeAll(visitedWordsInThisLevel);
visitedWordsInThisLevel.clear();
}
currentLevel = level;
char[] wordCharArray = word.toCharArray();
for (int i = 0; i < word.length(); ++i) {
char originalChar = wordCharArray[i];
boolean foundInThisCycle = false;
for (char c = 'a'; c <= 'z'; ++c) {
wordCharArray[i] = c;
String newWord = new String(wordCharArray);
if (c != originalChar && dict.contains(newWord)) {
maps.get(newWord).add(word);
if (newWord.equals(end)) {
found = true;
finalLevel = currentLevel;
foundInThisCycle = true;
break;
}
if (visitedWordsInThisLevel.add(newWord)) {
queue.add(new Node(newWord, currentLevel + 1));
}
}
}
if (foundInThisCycle) {
break;
}
wordCharArray[i] = originalChar;
}
}
if(found){
List<String> tmplist = new LinkedList<>();
generatePath(end,start,tmplist);
}
return res;
}
private void generatePath(String start,String end,List<String> list){
if(start.equals(end)){
List<String> tmplist = new LinkedList<>(list);
tmplist.add(end);
Collections.reverse(tmplist);
res.add(tmplist);
return;
}
list.add(start);
List<String> tmplist = maps.get(start);
for(String e:tmplist)
generatePath(e,end,list);
list.remove(list.size()-1);
}
}