Leetcode 126. Word Ladder II[hard]

15 篇文章 0 订阅
2 篇文章 0 订阅

题目:
Given two words (beginWord and endWord), and a dictionary’s word list, find all shortest transformation sequence(s) from beginWord to endWord, such that:

Only one letter can be changed at a time
Each intermediate word must exist in the word list
For example,

Given:
beginWord = “hit”
endWord = “cog”
wordList = [“hot”,”dot”,”dog”,”lot”,”log”]
Return
[
[“hit”,”hot”,”dot”,”dog”,”cog”],
[“hit”,”hot”,”lot”,”log”,”cog”]
]
Note:
All words have the same length.
All words contain only lowercase alphabetic characters.


这个题是真的烦,MLE,TLE,CLE真的是服了。
言归正传,经典题。将每个单词抽象成节点,相差一个字母的两个单词连边。
此题要求输出最短的词梯,所以使用bfs,找到最短词梯的长度。
题目还要输出所有的最短词梯,且考虑到所有最短词梯构成的并不一定是树,所以要使用dfs在bfs访问过的节点的基础上再次搜索。
为了方便dfs,在bfs的时候记录每个节点的step(从起始节点到当前节点的词梯长度),依据这个参数我们就可以还原bfs的搜索顺序了。

通过这个题,我还知道了,原来map中count比取值要快辣么多。。。。

这里写图片描述

class Solution {
public:
    vector< vector<string> > ans;
    vector<string> word;
    vector<bool> vis;
    unordered_map<string, int> mp;
    vector<int> q;
    vector<string> tans;
    vector<int> step; 
    int minstep;

    vector< vector<string> > findLadders(string beginWord, string endWord, unordered_set<string> &wordList) {
        minstep = -1;
        prep(wordList);
        bfs(mp[beginWord], mp[endWord]);

        if (minstep != -1) {
            tans.clear();
            tans.resize(minstep + 1);
            dfs(mp[endWord]);
        }
        return ans;
    }

    void prep(unordered_set<string> &wordList) {
        mp.clear();
        ans.clear();
        word.clear();

        word.push_back("null");
        unordered_set<string>::iterator it;
        int cnt = 0;
        for (it = wordList.begin(); it != wordList.end(); it++) {
            mp[*it] = ++cnt;
            word.push_back(*it);
        }

        vis.resize(cnt + 1);
        step.resize(cnt + 1);
    }

    void bfs(int ax, int ay) {
        int h = 0, t = 1;
        q.clear();
        q.push_back(ax);
        vis[ax] = true;
        step[ax] = 0;

        int len, num, sto;
        char cc;

        while (h < t) {
            num = q[h];
            if (num == ay) {
                minstep = step[num];
                return;
            }

            string str = word[num];
            len = str.length();
            for (int j = 0; j < len; j++) {
                cc = str[j];
                for (char k = 'a'; k <= 'z'; k++) {
                    if (cc != k) {
                        str[j] = k;
                        if (mp.count(str) == 0) continue;
                        sto = mp[str];
                        if (!vis[sto]) {
                            q.push_back(sto);
                            vis[sto] = true;
                            step[sto] = step[num] + 1;
                            t++;
                        }
                    }
                }
                str[j] = cc;
            }
            h++;
        }

    }

    void dfs(int x) {
        tans[step[x]] = word[x];
        if (step[x] == 0) {
            ans.push_back(tans);
            return;
        }
        string str = word[x];
        int len = str.length();
        for (int j = 0; j < len; j++) {
            char cc = str[j];
            for (char k = 'a'; k <= 'z'; k++) {
                if (cc != k) {
                    str[j] = k;
                    if (mp.count(str) == 0) continue;
                    int sto = mp[str];
                    if (vis[sto] && step[sto] + 1 == step[x]) dfs(sto);
                }
            }
            str[j] = cc;
        }
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值