刷题打卡:字符串操作の单词接龙 II

124 阅读1分钟

Offer 驾到,掘友接招!我正在参与2022春招系列活动-刷题打卡任务,点击查看活动详情

一、题目描述:

单词接龙 II

按字典 wordList 完成从单词 beginWord 到单词 endWord 转化,一个表示此过程的 转换序列 是形式上像 beginWord -> s1 -> s2 -> ... -> sk 这样的单词序列,并满足:

每对相邻的单词之间仅有单个字母不同。

转换过程中的每个单词 si(1 <= i <= k)必须是字典 wordList 中的单词。注意,beginWord 不必是字典 wordList 中的单词。 sk == endWord

给你两个单词 beginWord 和 endWord ,以及一个字典 wordList 。请你找出并返回所有从 beginWord 到 endWord 的 最短转换序列 ,如果不存在这样的转换序列,返回一个空列表。每个序列都应该以单词列表 [beginWord, s1, s2, ..., sk] 的形式返回。

示例 1:

输入:beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log","cog"]
输出:[["hit","hot","dot","dog","cog"],["hit","hot","lot","log","cog"]]
解释:存在 2 种最短的转换序列:
"hit" -> "hot" -> "dot" -> "dog" -> "cog"
"hit" -> "hot" -> "lot" -> "log" -> "cog"

示例 2:

输入:beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log"]
输出:[]
解释:endWord "cog" 不在字典 wordList 中,所以不存在符合要求的转换序列。

二、思路与实现:

思路:

通过使用双向BFS + 入队节点,构建正方向的有向无环图 dag。 DFS 在 dag 中收集所有连通路径(路径只要连通就是最短),记忆当前节点到终点的路径

代码实现:

/**
 * @param {string} beginWord
 * @param {string} endWord
 * @param {string[]} wordList
 * @return {string[][]}
 */
var findLadders = function(beginWord, endWord, wordList) {
    let wordSet = new Set(wordList);
    if (!wordSet.has(endWord)) return [];
    wordSet.delete(beginWord);
    let beginSet = new Set([beginWord]);
    let map = new Map();
    let distance = 0;
    let minDistance = 0;
    while(beginSet.size) {
        if (beginSet.has(endWord)) break;
        let trySet = new Set();
        for (let word of beginSet) {
            let mapSet = new Set();
            for (let i = 0; i < word.length; i++) {
                for (let j = 0; j < 26; j++) {
                    let tryWord = word.slice(0, i) + String.fromCharCode(97 + j) + word.slice(i + 1);
                    if (!minDistance && tryWord === endWord) minDistance = distance + 1;
                    if (wordSet.has(tryWord)) {
                        trySet.add(tryWord);
                        mapSet.add(tryWord);
                    }
                }
            }
            map.set(word, mapSet);
        }
        distance++;
        for (let w of trySet) {
            wordSet.delete(w);
        }
        beginSet = trySet;
    }
    let ans = [];
    let path = [beginWord];
    dfs(beginWord, endWord, ans, path, map, minDistance, 0);
    return ans;
};

function dfs (beginWord, endWord, ans, path, map, minDistance, distance) {
    if (distance > minDistance) return ;
    if (beginWord === endWord) {
        ans.push(path.slice());
    }
    let words = map.get(beginWord)
    if (words) {
        for (let word of words) {
            path.push(word)
            dfs(word, endWord, ans, path, map, minDistance, distance + 1);
            path.pop();
        }
    }
}

三、总结:

本题先用 BFS 求出最短距离,再用 DFS 求出最短距离路径即得解。BFS 和 DFS 是真的重要呀~