*** 126. Word Ladder II
解法一#
思路#
一个思路是通过 DFS 解决这道题。从 beginWord 开始,在字典中找出所有可能与之相邻的单词,即与之差一个字母的单词。对于所有的这些单词,再进行 DFS。递归出口是:如果查到 endWord, 将路径添加到结果中。如果查找到的路径比在结果集中的路径短,把之前的结果清除,添加新的最短路径。如果当前查询路径比已经查询到的最短路径长,终止查询。
获取一个 word 所有与之相邻的 words,可以将这个字母每一位分别用 26 个字母代替,和 wordList 比较。代码如下:
public ArrayList<String> findNeighbors(String curr, Set<String> wordSet) {
char[] chars = curr.toCharArray();
ArrayList<String> neighbors = new ArrayList<>();
for (int i = 0; i < chars.length; i++) {
char old = chars[i];
for (char j = 'a', j <= 'z'; j++) {
if (j == old) continue;
chars[i] = j;
String newStr = new String(chars);
if (set.contains(newStr)) {
neighbors.add(newStr);
}
}
chars[i] = old; // Restore the word
}
return neighbors;
}
递归出口如下:
// ans list has the resulting paths
// min is the length of the shortest path
// temp is the current path
if (beginWord.equals(endWord)) {
if (temp.size < min) {
ans.clear();
ans.add(new ArrayList<String>(temp));
min = temp.size();
} else if (temp.size() == min) {
ans.add(new ArrayList<String>(temp));
}
}
if (temp.size() > min) {
return;
}
随后我们可以用递归实现 DFS 来得到最短路径。
代码#
Class Solution{
public List<List<String>> findLadders(String beginWord, String endWord, List<String> wordList) {
List<List<String>> ans = new ArrayList<>();
ArrayList<String> temp = new ArrayList<>();
Set<String> dict = new HashSet<>(wordList);
temp.add(beginWord);
findLaddersHelper(beginWord, endWord, dict, ans, temp);
return ans;
}
private int min = Integer.MAX_VALUE;
public void findLaddersHelper(String beginWord, String endWord, Set<String> dict, List<List<String>> ans, ArrayList<String> temp) {
if (beginWord.equals(endWord)) {
if (temp.size() < min) {
ans.clear();
ans.add(new ArrayList<String>(temp));
min = temp.size();
} else {
ans.add(new ArrayList<String>(temp));
}
}
if (temp.size() > min) {
return;
}
List<String> neighbors = findNeighbors(beginWord, dict);
for (String neighbor : neighbors) {
if (temp.contains(neighbor)) // if neighbor is already in temp, skip to next neighbor
continue;
temp.add(neighbor);
findLaddersHelper(neighbor, endWord, dict, ans, temp);
temp.remove(temp.size() - 1); // ?????
}
}
public ArrayList<String> findNeighbors(String curr, Set<String> dict) {
ArrayList<String> neighbors = new ArrayList<>();
char[] chars = curr.toCharArray();
// Substitute each character with a - z
for (int i = 0; i < chars.length; i++) {
char old = chars[i];
for (char c = 'a'; c <= 'z'; c++) {
if (c == old) {
continue;
}
chars[i] = c;
String newWord = new String(chars);
if (dict.contains(newWord)) {
neighbors.add(newWord);
}
}
chars[i] = old;
}
return neighbors;
}
}
复杂度分析#
- 时间复杂度
这个算法含有过多不必要的重复遍历,说以会超时。 - 空间复杂度
解法二#
思路#
代码#
复杂度分析#
- 时间复杂度
- 最好情况
- 最坏情况
- 平均情况
- 空间复杂度
Takeaway#
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: