单词接龙 II

给出两个单词(start和end)和一个字典,找出所有从start到end的最短转换序列

比如:

  1. 每次只能改变一个字母。
  2. 变换过程中的中间单词必须在字典中出现。
样例

给出数据如下:

start = "hit"

end = "cog"

dict = ["hot","dot","dog","lot","log"]

返回

[

    ["hit","hot","dot","dog","cog"],

    ["hit","hot","lot","log","cog"]

  ]

注意
  • 所有单词具有相同的长度。
  • 所有单词都只包含小写字母。

class Solution {
public:
    /**
      * @param start, a string
      * @param end, a string
      * @param dict, a set of string
      * @return a list of lists of string
      */
    vector<vector<string>> findLadders(string start, string end, unordered_set<string> &dict) {
        // write your code here
        vector<vector<string> > result;
        set<string> cur;
        cur.insert(start);
        set<string> next;
        map<string, set<string> > parents;

        unordered_set<string> unused = dict;
        unused.insert(end);

        visit(cur, end, next, unused, parents);
        if (parents.find(end) != parents.end())
        {
            vector<string> buf;
            generatePath(start, end, parents, buf, result);
        }

        return result;
    }
private:
    void visit(set<string> &cur, string &end, set<string> &next, 
               unordered_set<string> &unused, map<string, set<string> > &parents)
    {
        while (parents.find(end) == parents.end() && !unused.empty())
        {
            next.clear();
            for (set<string>::iterator it = cur.begin(); it != cur.end(); it++)
            {
                string word = *it;
                string temp = *it;
                for (int i = 0; i < (*it).length(); i++)
                {
                    for (char a = 'a'; a <= 'z'; a++)
                    {
                        temp = *it;
                        if (a != word[i])
                        {
                            temp[i] = a;
                            if (unused.find(temp) != unused.end())
                            {
                                parents[temp].insert(word);
                                next.insert(temp);
                            }
                        }
                    }
                }
            }

            if (next.empty())
            {
                return;
            }

            cur = next;
            for (set<string>::iterator it = next.begin(); it != next.end(); it++)
            {
                unused.erase(*it);
            }
        }
    }

    void generatePath(string &start, string cur, map<string, set<string> > &parents, 
                  vector<string> &buf, vector<vector<string> > &result)
    {
        buf.insert(buf.begin(), cur);
        if (cur == start)
        {
            result.push_back(buf);
        }
        else
        {
            for (set<string>::iterator it = parents[cur].begin(); it != parents[cur].end(); it++)
            {
                generatePath(start, *it, parents, buf, result);
            }
        }

        buf.erase(buf.begin());
    }
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值