20190423-Leetcode-126.单词接龙2

Leetcode-126.单词接龙2

给定两个单词(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.构建结点之间的图关系,把一个个字符串作为结点,然后经过一次变换能得到的字符串作为邻接结点,(注意:一定要考虑给定的字符串中是否包含了开始结点)
用unordered_map<string, vector > graph实现
2.用vector all_node最为队列记录关系,其中node中包含该字符串,以及字串变换来的前驱节点和现在的变换的次数,用unordered_map记录该节点最早出现的次数,在之后要是遍历到该结点,若是出现过并且步数超过记录的,则不用管。
3.先把开始结点放入all_node,并且不断遍历其邻接结点。判断结点,是否是最后的结点,若是则判断其是否超过第一次出现的时候的步长(需记录最后一个结点第一次出现的步长),若超过则直接停止循环,若没有,把记录最后结点的位置(用数组记录最后结点的位置)。判断邻接结点若没有出现过,则加入all_node,并记录其前驱和步长,若出现过判断是否是刚出现过还是之前出现过,若是之前出现过,则该节点不用管。

代码

class Solution {
public:
    struct node{
        string s;
        int left;
        int step;
        node(string s, int left, int step):s(s), left(left), step(step){}
    };
    bool connect(string &Word1, string &Word2){
        int count = 0;
        for(int i = 0; i < Word2.size(); i++){
            if(Word1[i] != Word2[i]){
                count++;
            }
        }
        return count == 1;
    }
    void construct_graph(string &beginWord, unordered_map<string, vector<string> > &graph, vector<string>& wordList){
        int flag = 0;
        for(int i = 0; i < wordList.size(); i++){
            graph[wordList[i]] = vector<string>();
            if(beginWord == wordList[i]){
                flag = 1;
            }
        }

        for(int i = 0; i < wordList.size(); i++){
            for(int j = i + 1; j < wordList.size(); j++){
                if(connect(wordList[i], wordList[j])){
                    graph[wordList[i]].push_back(wordList[j]);
                    graph[wordList[j]].push_back(wordList[i]);
                }
            }
            if(flag == 0 && connect(beginWord, wordList[i])){
                graph[beginWord].push_back(wordList[i]);
            }
        }
    }
    vector<vector<string>> findLadders(string beginWord, string endWord, vector<string>& wordList) {
        unordered_map<string, vector<string> > graph;
        construct_graph(beginWord, graph, wordList);
        vector<node> all_node;
        unordered_map<string, int> nodes_step;
        all_node.push_back(node(beginWord, -1, 1));
        nodes_step[beginWord] = 1;
        int begin = 0;
        int min_step = 0;
        vector<int> end_node_id;
        while(begin < all_node.size()){
            string s_temp = all_node[begin].s;
            int step_temp = all_node[begin].step;
            if(min_step != 0 && step_temp > min_step){
                break;
            }
            if(s_temp == endWord){
                min_step = step_temp;
                end_node_id.push_back(begin);
            }
            vector<string> neighbors = graph[s_temp];
            for(int i = 0; i < neighbors.size(); i++){
                if(nodes_step.find(neighbors[i]) == nodes_step.end() || nodes_step[neighbors[i]] == step_temp+1){
                    all_node.push_back(node(neighbors[i], begin, step_temp+1));
                    nodes_step[neighbors[i]] = step_temp + 1;
                }
            }
            begin++;
        }
        vector<vector<string> > res;
        for(int i = 0; i < end_node_id.size(); i++){
            vector<string> res_temp;
            int end_id = end_node_id[i];
            while(end_id != -1){
                res_temp.insert(res_temp.begin(), all_node[end_id].s);
                end_id = all_node[end_id].left;
            }
            res.push_back(res_temp);
        }
        
        return res;
        
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值