单词接龙

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

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

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

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

输出: 5

解释: 一个最短转换序列是 "hit" -> "hot" -> "dot" -> "dog" -> "cog",
返回它的长度 5。
示例 2:

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

输出: 0

解释: endWord "cog" 不在字典中,所以无法进行转换。

class Solution {
    //1.通过使用虚拟节点进行建图
    //2.最近距离问题一般采用广度优先算法进行相应的处理
public:
    unordered_map<string,int> wordId;
    vector<vector<int>> edge;
    int nodeNum = 0;

    void addWord(string& word){
        if(!wordId.count(word)){
            wordId[word] = nodeNum++;
            edge.emplace_back();
            //先预留一个vector,供其他函数插入操作使用
        }
    }
    void addEdge(string& word){
        addWord(word);
        int id1 = wordId[word];
        for(char& it:word){
            char tmp = it;
            it = '*';
            addWord(word);
            int id2 = wordId[word];
            edge[id1].push_back(id2);
            edge[id2].push_back(id1);//插入虚拟节点
            it = tmp;//还原word
        }
    }

    int ladderLength(string beginWord, string endWord, vector<string>& wordList) {
        for(string& word: wordList){
            addEdge(word);
        }
        addEdge(beginWord);
        if(!wordId.count(endWord)){
            return 0;//序列中没有终点,直接返回0
        }
        vector<int> dis(nodeNum,INT_MAX);
        //准备开始进行广度优先搜索
        int beginId = wordId[beginWord],endId = wordId[endWord];
        dis[beginId] = 0;

        queue<int> que;
        que.push(beginId);
        while(!que.empty()){
            int x = que.front();
            que.pop();
            if(x == endId){
                return dis[endId]/2 +1;//找到最终的节点
                //由于加了虚拟节点,所以路径的长度等于扩大了一倍
                //同时由于计算的应该是节点的个数,所以/2后还需要再进行加1操作
            }
            for(int& it:edge[x]){
                if(dis[it] == INT_MAX){
                    dis[it] = dis[x]+1;
                    que.push(it);
                }
            }
        }
        return 0;
    }
};

注意:

1.最短路径问题想到使用广度优先算法。

2.注意使用虚拟节点的方法。

posted @ 2020-11-05 21:14  zmachine  阅读(177)  评论(0编辑  收藏  举报