package class31; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Queue; public class Problem_0127_WordLadder { // start,出发的单词 // to, 目标单位 // list, 列表 // to 一定属于list // start未必 // 返回变幻的最短路径长度 public static int ladderLength1(String start, String to, List list) { list.add(start); // key : 列表中的单词,每一个单词都会有记录! // value : key这个单词,有哪些邻居! HashMap> nexts = getNexts(list); // abc 出发 abc -> abc 0 // // bbc 1 HashMap distanceMap = new HashMap<>(); distanceMap.put(start, 1); HashSet set = new HashSet<>(); set.add(start); Queue queue = new LinkedList<>(); queue.add(start); while (!queue.isEmpty()) { String cur = queue.poll(); Integer distance = distanceMap.get(cur); for (String next : nexts.get(cur)) { if (next.equals(to)) { return distance + 1; } if (!set.contains(next)) { set.add(next); queue.add(next); distanceMap.put(next, distance + 1); } } } return 0; } public static HashMap> getNexts(List words) { HashSet dict = new HashSet<>(words); HashMap> nexts = new HashMap<>(); for (int i = 0; i < words.size(); i++) { nexts.put(words.get(i), getNext(words.get(i), dict)); } return nexts; } // 应该根据具体数据状况决定用什么来找邻居 // 1)如果字符串长度比较短,字符串数量比较多,以下方法适合 // 2)如果字符串长度比较长,字符串数量比较少,以下方法不适合 public static ArrayList getNext(String word, HashSet dict) { ArrayList res = new ArrayList(); char[] chs = word.toCharArray(); for (int i = 0; i < chs.length; i++) { for (char cur = 'a'; cur <= 'z'; cur++) { 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; } public static int ladderLength2(String beginWord, String endWord, List wordList) { HashSet dict = new HashSet<>(wordList); if (!dict.contains(endWord)) { return 0; } HashSet startSet = new HashSet<>(); HashSet endSet = new HashSet<>(); HashSet visit = new HashSet<>(); startSet.add(beginWord); endSet.add(endWord); for (int len = 2; !startSet.isEmpty(); len++) { // startSet是较小的,endSet是较大的 HashSet nextSet = new HashSet<>(); for (String w : startSet) { // w -> a(nextSet) // a b c // 0 // 1 // 2 for (int j = 0; j < w.length(); j++) { char[] ch = w.toCharArray(); for (char c = 'a'; c <= 'z'; c++) { if (c != w.charAt(j)) { ch[j] = c; String next = String.valueOf(ch); if (endSet.contains(next)) { return len; } if (dict.contains(next) && !visit.contains(next)) { nextSet.add(next); visit.add(next); } } } } } // startSet(小) -> nextSet(某个大小) 和 endSet大小来比 startSet = (nextSet.size() < endSet.size()) ? nextSet : endSet; endSet = (startSet == nextSet) ? endSet : nextSet; } return 0; } }