给定字典中的两个词,长度相等。写一个方法,把一个词转换成另一个词, 但是一次只能改变一个字符。每一步得到的新词都必须能在字典中找到。
编写一个程序,返回一个可能的转换序列。如有多个可能的转换序列,你可以返回任何一个。
示例 1:
输入:
beginWord = “hit”,
endWord = “cog”,
wordList = [“hot”,“dot”,“dog”,“lot”,“log”,“cog”]
输出:
[“hit”,“hot”,“dot”,“lot”,“log”,“cog”]
使用BFS即可,设置一个boolean[]数组用于记录字典中的字符串是否被访问过,利用map来存储字符串和对应的其前驱(也就是只有一个字符不同的字符串)
- 首先先判断endWord是否在字典中,如果不在可以直接返回结果了
- 用一个队列将beginWord放进去,然后通过BFS的方式遍历找到对应的前驱字符串,并将其前驱关系存放在map中
- 如果最终没有到达endWord那说明就是没有结果 可以直接返回了
- 如果最终能够到达endWord说明有路径可以满足
- 因为map中存放的关系是从后往前的前驱关系,所以从后往前遍历找到答案即可
public static List<String> findLadders(String beginWord, String endWord, List<String> wordList) {
Queue<String> queue = new LinkedList<>();
List<String> ans = new ArrayList<>();
//存放每个单词的前驱,比如hot的前驱可以是hit,lot等;
HashMap<String, String> map = new HashMap<>();
//标记是否被访问过
boolean[] visited = new boolean[wordList.size()];
if (!wordList.contains(endWord)) {
return ans;
}
queue.add(beginWord);
boolean flag = false;
//BFS
while (!queue.isEmpty()) {
String strHead = queue.poll();
//这里是有答案的情况下循环的出口
if (strHead.equals(endWord)) {
flag = true;
break;
}
//寻找当前单词strHead的所有前驱
for (int i = 0; i < wordList.size(); i++) {
//如果未被访问过并且可以直接转换,则加入队列
//compare()函数用来判断是否可以转换
if (visited[i] == false && compare(wordList.get(i), strHead)) {
queue.add(wordList.get(i));
visited[i] = true;
map.put(wordList.get(i), strHead);
}
}
}
//说明在刚才的循环中没有找到可能的路径
if (flag == false) {
return ans;
}
//遍历答案
String key = endWord;
while (key != beginWord) {
ans.add(key);
key = map.get(key);
}
ans.add(key);
Collections.reverse(ans);
return ans;
}
//判断两个字符串之间的差距是否大于1
public static boolean compare(String str, String str2) {
int diff = 0;
for (int i = 0; i < str.length(); i++) {
if (str.charAt(i) != str2.charAt(i)) {
diff++;
if (diff >= 2) return false;
}
}
return true;
}