*** 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 协议》,转载必须注明作者和本文链接
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!