126. 单词接龙 II - 力扣(LeetCode)

题目描述

给定两个单词(beginWord 和 endWord)和一个字典 wordList,找出所有从 beginWord 到 endWord 的最短转换序列。转换需遵循如下规则:

每次转换只能改变一个字母。
转换过程中的中间单词必须是字典中的单词。
说明:

如果不存在这样的转换序列,返回一个空列表。
所有单词具有相同的长度。
所有单词只由小写字母组成。
字典中不存在重复的单词。
你可以假设 beginWord 和 endWord 是非空的,且二者不相同。
示例 1:

输入:
beginWord = “hit”,
endWord = “cog”,
wordList = [“hot”,“dot”,“dog”,“lot”,“log”,“cog”]

输出:
[
[“hit”,“hot”,“dot”,“dog”,“cog”],
[“hit”,“hot”,“lot”,“log”,“cog”]
]
示例 2:

输入:
beginWord = “hit”
endWord = “cog”
wordList = [“hot”,“dot”,“dog”,“lot”,“log”]

输出: []

解释: endWord “cog” 不在字典中,所以不存在符合要求的转换序列。

题解1

寻找一个单词到另一个单词的最短转换序列(可能存在多个)。可以将每个单词看成图中的结点,两个单词转换规则是每次只能替换一个字母,相当于若两个单词只有一个字母不同,相当于两个结点有一条无向边相连。最后问题转化成求两个结点间的最短路径。
求最短路径用BFS或者dijkstra等算法均可,但这里需要求多条最短路径,用dijkstra算法更好。
注意:startWord与endWord可能都不在字典中,需要判断startWord是否在字典中,如果没有需要加入,作为路径的起点。

代码1

/*
将字典转为图,问题转为两点间的最短路径
*/
vector<string>words;
map<string, int>idxs;
map<string, vector<string>>pre;//存储前一个结点列表,因为可能存在多条最短路径
map<string, int>dist;
vector<string>tmp;
bool isSim(string a, string b){
    int cnt = 0;
    for(int i  = 0; i < a.size(); ++i){
        if(a[i] != b[i]){
            ++cnt;
        }
    }
    return cnt == 1;
}

void dfs(vector<vector<string>>& res, vector<vector<int>>& pre, int u, int v){//递归生成多条路径
    if(u == v){
        
        res.push_back(tmp);
        //tmp.pop_back();
        return;
    }
    
    for(int i = 0; i < pre[u].size(); ++i){
        tmp.push_back(words[pre[u][i]]);
        dfs(res, pre, pre[u][i], v);
        tmp.pop_back();//恢复环境
    }
}
vector<vector<string>> dijkstra(vector<vector<int>>& gra, int u, int v){//dijkstra求最短路
    
    int n = gra.size();
    int MAX = 1 << 30;
    int MIN = -(1 << 30);
    int minVal = MAX, idx;
    vector<bool>mark(n, false);
    vector<int>dist(n, MAX);
    vector<vector<int>>pre(n, vector<int>());
    vector<vector<string>>res;
    for(int i = 0; i < gra[u].size(); ++i){
        pre[gra[u][i]] = vector<int>({u});
        dist[gra[u][i]] = 1;
    }
    mark[u] = true;
    for(int i = 0; i < n; ++i){
        minVal = MAX;
        idx = -1;
        for(int j = 0; j < n; ++j){
            if(!mark[j] && dist[j] < minVal){
                minVal = dist[j];
                idx = j;
            }
        }
        if(idx != -1){
            mark[idx] = true;
            for(int k = 0; k < gra[idx].size(); ++k){
                int v = gra[idx][k];
                if(!mark[v] && dist[v] > dist[idx] + 1){
                    dist[v] = dist[idx] + 1;
                    pre[v].clear();
                    pre[v].push_back(idx);
                }
                else if(!mark[v] && dist[v] == dist[idx] + 1){
                    pre[v].push_back(idx);
                }
            }
        }
        
    }

    //路径
    if(pre[v].empty()){
        return res;
    }
    else{
        tmp.clear();//清空
        tmp.push_back(words[v]);
        
        dfs(res, pre, v, u);
        for(int i = 0; i < res.size(); ++i){
            reverse(res[i].begin(), res[i].end());
        }
        return res;
    }
}

class Solution {
public:
    vector<vector<string>> findLadders(string beginWord, string endWord, vector<string>& wordList) {
        words.assign(wordList.begin(), wordList.end());
        
        idxs.clear();//清空
        pre.clear();
        dist.clear();

        bool flag = false;
        for(int i = 0; i < wordList.size(); ++i){//建立字符串与下标的映射
            idxs[wordList[i]] = i;
            if(wordList[i] == beginWord){
                flag = true;
            }
        }
        if(!flag){
            words.push_back(beginWord);
            idxs[beginWord] = wordList.size();
        }
        int len = words.size();
       
        vector<vector<int>>gra(len, vector<int>());//建立邻接表        
        
        for(int i = 0; i < len; ++i){//建立图
            for(int j = i + 1; j < len; ++j){
                if(isSim(words[i], words[j])){
                    gra[i].push_back(j);
                    gra[j].push_back(i);
                }
            }
        }           
        if(idxs.find(endWord) == idxs.end()){
            return vector<vector<string>>();
        }
        return dijkstra(gra, idxs[beginWord], idxs[endWord]);
    }
};

执行结果1

126. 单词接龙 II - 力扣(LeetCode)_第1张图片

你可能感兴趣的:(LeetCode)