给定字典中的两个词,长度相等。写一个方法,把一个词转换成另一个词, 但是一次只能改变一个字符。每一步得到的新词都必须能在字典中找到。
编写一个程序,返回一个可能的转换序列。如有多个可能的转换序列,你可以返回任何一个。
示例 1:
输入:
beginWord = "hit",
endWord = "cog",
wordList = ["hot","dot","dog","lot","log","cog"]
输出:
["hit","hot","dot","lot","log","cog"]
示例 2:
输入:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log"]
输出: []
解释: endWord "cog" 不在字典中,所以不存在符合要求的转换序列。
方法1:BFS+List
public List<String> findLadders(String beginWord, String endWord, List<String> wordList) {
Queue<String> q = new LinkedList<>();
q.offer(beginWord);
Set<String> words = new HashSet<>(wordList);
Map<String, String> vis = new HashMap<>();
List<String> res = new ArrayList<>();
vis.put(beginWord, beginWord);
while (!q.isEmpty()) {
int size = q.size();
for (int i = 0; i < size; i++) {
String cur = q.poll();
if (cur.equals(endWord)) {
res.add(0, endWord);
String t = endWord;
while (!t.equals(beginWord)) {
t = vis.get(t);
res.add(0, t);
}
return res;
}
List<String> cans = transform(words, cur);
for (String can : cans) {
if (!vis.containsKey(can)) {
vis.put(can, cur);
q.offer(can);
}
}
}
}
return new ArrayList<>();
}
private List<String> transform(Set<String> words, String word) {
List<String> resList = new ArrayList<>();
StringBuffer sb = new StringBuffer(word);
for (int i = 0; i < sb.length(); i++) {
char tmp = sb.charAt(i);
for (char c = 'a'; c <= 'z'; c++) {
if (tmp == c) continue;
sb.setCharAt(i, c);
String canditate = sb.toString();
if (words.remove(canditate)) resList.add(canditate);
}
sb.setCharAt(i, tmp);
}
return resList;
}
方法2:BFS+Stack
public List<String> findLadders(String beginWord, String endWord, List<String> wordList) {
Set<String> words = new HashSet<>(wordList);
Map<String, String> vis = new HashMap<>();
Queue<String> q = new LinkedList<>();
q.offer(beginWord);
vis.put(beginWord, beginWord);
Stack<String> stk = new Stack<>();
while (!q.isEmpty()) {
int size = q.size();
for (int i = 0; i < size; i++) {
String cur = q.poll();
if (cur.equals(endWord)) {
stk.push(endWord);
String t = endWord;
while (!t.equals(beginWord)) {
t = vis.get(t);
stk.push(t);
}
List<String> res = new ArrayList<>();
while (!stk.isEmpty()) res.add(stk.pop());
return res;
}
for (String next : words) {
if (isNext(cur, next) && !vis.containsKey(next)) {
vis.put(next, cur);
q.offer(next);
}
}
}
}
return new ArrayList<>();
}
public boolean isNext(String cur, String next) {
int cnt = 0;
for (int i = 0; i < cur.length(); i++) {
if (cur.charAt(i) != next.charAt(i)) cnt++;
}
return cnt == 1;
}
方法3:DFS
List<String> res = new ArrayList<>();
List<String> wordList;
String endWord;
Set<String> vis = new HashSet<>();
public List<String> findLadders(String beginWord, String endWord, List<String> wordList) {
this.wordList = wordList;
this.endWord = endWord;
res.add(beginWord);
vis.add(beginWord);
return dfs(beginWord) ? res : new ArrayList<>();
}
public boolean dfs(String cur) {
if (cur.equals(endWord)) return true;
for (String next : wordList) {
if (isNext(cur, next) && !vis.contains(next)) {
vis.add(next);
res.add(next);
if (dfs(next)) return true;
else {
res.remove(res.size() - 1);
}
}
}
return false;
}
public boolean isNext(String cur, String next) {
int cnt = 0;
for (int i = 0; i < cur.length(); i++) {
if (cur.charAt(i) != next.charAt(i)) cnt++;
}
return cnt == 1;
}