You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

101 lines
3.4 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package class26;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
// 本题测试链接 : https://leetcode.com/problems/word-ladder-ii/
public class Code04_WordLadderII {
public static List<List<String>> findLadders(String start, String end, List<String> list) {
list.add(start);
HashMap<String, List<String>> nexts = getNexts(list);
HashMap<String, Integer> fromDistances = getDistances(start, nexts);
List<List<String>> res = new ArrayList<>();
if (!fromDistances.containsKey(end)) {
return res;
}
HashMap<String, Integer> toDistances = getDistances(end, nexts);
LinkedList<String> pathList = new LinkedList<>();
getShortestPaths(start, end, nexts, fromDistances, toDistances, pathList, res);
return res;
}
public static HashMap<String, List<String>> getNexts(List<String> words) {
HashSet<String> dict = new HashSet<>(words);
HashMap<String, List<String>> nexts = new HashMap<>();
for (int i = 0; i < words.size(); i++) {
nexts.put(words.get(i), getNext(words.get(i), dict));
}
return nexts;
}
// word, 在表中有哪些邻居把邻居们生成list返回
public static List<String> getNext(String word, HashSet<String> dict) {
ArrayList<String> res = new ArrayList<String>();
char[] chs = word.toCharArray();
for (char cur = 'a'; cur <= 'z'; cur++) {
for (int i = 0; i < chs.length; i++) {
if (chs[i] != cur) {
char tmp = chs[i];
chs[i] = cur;
if (dict.contains(String.valueOf(chs))) {
res.add(String.valueOf(chs));
}
chs[i] = tmp;
}
}
}
return res;
}
// 生成距离表从start开始根据邻居表宽度优先遍历对于能够遇到的所有字符串生成(字符串,距离)这条记录,放入距离表中
public static HashMap<String, Integer> getDistances(String start, HashMap<String, List<String>> nexts) {
HashMap<String, Integer> distances = new HashMap<>();
distances.put(start, 0);
Queue<String> queue = new LinkedList<>();
queue.add(start);
HashSet<String> set = new HashSet<>();
set.add(start);
while (!queue.isEmpty()) {
String cur = queue.poll();
for (String next : nexts.get(cur)) {
if (!set.contains(next)) {
distances.put(next, distances.get(cur) + 1);
queue.add(next);
set.add(next);
}
}
}
return distances;
}
// cur 当前来到的字符串 可变
// to 目标,固定参数
// nexts 每一个字符串的邻居表
// cur 到开头距离5 -> 到开头距离是6的支路 fromDistances距离表
// cur 到结尾距离5 -> 到开头距离是4的支路 toDistances距离表
// path : 来到cur之前深度优先遍历之前的历史是什么
// res : 当遇到cur把历史放入res作为一个结果
public static void getShortestPaths(String cur, String to, HashMap<String, List<String>> nexts,
HashMap<String, Integer> fromDistances, HashMap<String, Integer> toDistances, LinkedList<String> path,
List<List<String>> res) {
path.add(cur);
if (to.equals(cur)) {
res.add(new LinkedList<String>(path));
} else {
for (String next : nexts.get(cur)) {
if (fromDistances.get(next) == fromDistances.get(cur) + 1
&& toDistances.get(next) == toDistances.get(cur) - 1) {
getShortestPaths(next, to, nexts, fromDistances, toDistances, path, res);
}
}
}
path.pollLast();
}
}