127.单词接龙
DFS(超时)
/**
* 算法一:暴力回溯
* 超时!!
* */
/**
*
* @param beginWord:src 字符串
* @param endWord:des 字符串
* @param wordList:字典
* @return 转换序列长度,即转换次数+1
*/
static boolean[] isVisited;
public static int ladderLength(String beginWord, String endWord, List<String> wordList) {
if (wordList == null || wordList.size() == 0 || !wordList.contains(endWord)) return 0;
isVisited = new boolean[wordList.size()+1];
int ans = dfs(beginWord,endWord,wordList);
return ans == Integer.MAX_VALUE ? 0 : ans;
}
private static int dfs(String beginWord,String endWord,List<String> wordList){
if (endWord.equals(beginWord))
return 1;
Map<String, Integer> map = withOneDifferent(beginWord, wordList);
int min = Integer.MAX_VALUE;
Iterator<String> iterator = map.keySet().iterator();
int cnt;
while (iterator.hasNext()){
String next = iterator.next();
isVisited[map.get(next)] = true;
cnt = dfs(next,endWord,wordList);
min = Math.min(min,cnt);
isVisited[map.get(next)] = false;
}
return min == Integer.MAX_VALUE ? Integer.MAX_VALUE : min+1;
}
/**
* 返回与str只有一个字母不同的单词列表
*/
private static Map<String,Integer> withOneDifferent(String str,List<String> wordList){
Map<String,Integer> map = new HashMap<>();
int n = wordList.get(0).length();
int l,r;
int index = 0;
for (String s : wordList){
if (isVisited[index++] || s.equals(str))
continue;
l = 0;
r = n-1;
while (l < n && s.charAt(l) == str.charAt(l))
l++;
while (r > l && s.charAt(r) == str.charAt(r))
r--;
if (l == r && s.charAt(l) != str.charAt(l))
map.put(s,index-1);
}
return map;
}
双向BFS
/**
* 双向bfs
*/
static Map<String,List<String>> match = new HashMap<>();
public static int ladderLength2(String beginWord, String endWord, List<String> wordList) {
if (!wordList.contains(endWord))
return 0;
int n = wordList.get(0).length();
//预处理
wordList.forEach(word ->{
for (int i = 0; i < n; i++) {
String state = word.substring(0,i)+"*"+word.substring(i+1,n);
List<String> list = match.getOrDefault(state, new ArrayList<>());
list.add(word);
match.put(state,list);
}
});
//双向dfs
Queue<Pair<String,Integer>> queueBeg = new LinkedList<>();
Queue<Pair<String,Integer>> queueEnd = new LinkedList<>();
queueBeg.offer(new Pair<>(beginWord,1));
queueEnd.offer(new Pair<>(endWord,1));
Map<String,Integer> isVisitBeg = new HashMap<>();
Map<String,Integer> isVisitEnd = new HashMap<>();
isVisitBeg.put(beginWord,1);
isVisitEnd.put(endWord,1);
int ans = 0;
while (!queueBeg.isEmpty() && !queueEnd.isEmpty()){
ans = bfs(queueBeg,isVisitBeg,isVisitEnd);
if (ans != -1)
return ans;
ans = bfs(queueEnd,isVisitEnd,isVisitBeg);
if (ans != -1)
return ans;
}
return 0;
}
/**
* 也就是,当双向dfs访问同一个节点时,说明找到了最短的路径
* @param queue: 队列
* @param isVisited:当前队列访问过的节点
* @param othersVisited:另一个方向的bfs所访问过的节点
* @return
*/
private static int bfs(Queue<Pair<String,Integer>> queue,Map<String,Integer> isVisited,Map<String,Integer> othersVisited){
Pair<String, Integer> pair = queue.remove();
String word = pair.getKey();
Integer floor = pair.getValue();
for (int i = 0; i < word.length(); i++) {
String state = word.substring(0,i)+"*"+word.substring(i+1,word.length());
List<String> list = match.getOrDefault(state, new ArrayList<>());
for (String adj : list){
if (othersVisited.containsKey(adj)){
return othersVisited.get(adj) + floor;
}else if (!isVisited.containsKey(adj)){
isVisited.put(adj,floor+1);
queue.add(new Pair<>(adj,floor+1));
}
}
}
return -1;
}