[LeetCode] Word Ladder

Word Ladder

Given two words (start and end), and a dictionary, find the length of shortest transformation sequence from start to end, such that:

  1. Only one letter can be changed at a time
  2. Each intermediate word must exist in the dictionary

For example,

Given:
start = "hit"
end = "cog"
dict = ["hot","dot","dog","lot","log"]

As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog",
return its length 5.

Note:

  • Return 0 if there is no such transformation sequence.
  • All words have the same length.
  • All words contain only lowercase alphabetic characters.

这道题数据规模dict.size() 最大4000+。

构建图(每两个可转换的单词连一条边)以后,bfs一边。

本身不难,不过非常容易超时。主要构建图是如果用N*N来搞的话,会超时。

加速1:

因此构建图可以采用别的方法:在找“hot”相邻的词时,可以改变hot中一个字符,例如“aot”,然后在dict里面找是否有。

这样的复杂度为O(N+N*logN*26*LEN), len为单词平均长度

只要26×len×LogN < N。那么就加速了。

加速2:

另外,其实构建图时,可以推迟构建全图。

每次要用到与某个词相邻的词时,再构建。这样会快点。

 

class Solution {
public:
 bool cmp(const string& a, const string& b) {
    if (a.size() != b.size()) return false;
    bool flag = false;
    for (int i = 0; i < a.size(); ++i) {
        if (a[i] != b[i]){
            if (flag == false)
                flag = true;
            else 
                return false;
        }
    }
    return flag;
}
void getNext(const string& tmp, const  unordered_set<string>& dict, vector<string> &v ) {
    for (int i = 0; i < tmp.size(); ++i) {
        for (int j = 0; j < 26; ++j) {
            if (tmp[i] == 'a' + j) continue;
            string t2 = tmp;
            t2[i] = 'a' + j;
            auto res = dict.find(t2);
            if (res != dict.end()){
                v.push_back(t2);
            }
        }
    }
}
int ladderLength(string start, string end, unordered_set<string> &dict) {
    int dsize = dict.size();

    queue<string> q;
    queue<int > l;
    unordered_set<string> visited;
    auto it = dict.find(start);
    if (it != dict.end()) {
        q.push(*it);
        visited.insert(*it);
        l.push(1);
    } else {
        for (auto i = dict.begin(); i != dict.end(); ++i) {
            if (cmp(start, *i)) {
                q.push(*i);
                visited.insert(*i);
                l.push(2);
            }
        }
    }

    int level;
    while (!q.empty()) {
        string cur = q.front(); q.pop();
        level = l.front(); l.pop();
        vector<string> v;
        getNext(cur, dict, v);
        for (int i = 0; i < v.size(); ++i) {
            if (v[i] == end) return level + 1;
        }
        for (int i = 0; i < v.size(); ++i) {
            if (visited.count(v[i]) == 0) {
                if (cmp(v[i], end))
                    return level + 2;
                else {
                    q.push(v[i]);
                    l.push(level + 1);
                    visited.insert(v[i]);
                }
            }
        }
    }
    return 0;
}
};

 

class Solution {
public:
    int ladderLength(string start, string end, unordered_set<string> &dict) {
        if (start == end) return 1;
        unordered_map<string, int> id;
        vector<string> str;
        int idx = 0;
        for (auto it = dict.begin(); it != dict.end(); ++it) {
            if (id.count(*it) > 0) continue;
            id[*it] = idx++;
            str.push_back(*it);
        }
        if (id.count(end) == 0) id[end] = idx++, str.push_back(end);
        int endid = id[end];
        vector<bool> vis(idx, false);
        
        queue<int> q;
        int level = 2;
        vector<int> next;
        getnext(id, start, vis, next);
        if (vis[endid]) return level;
        while (!next.empty()) {
            vector<int> cur(next);
            next.clear();
            for (int i = 0; i < cur.size(); i++) {
                getnext(id, str[cur[i]], vis, next);
                if (vis[endid]) return level+1;
            }
            level++;
        }
        return 0;
    }

    void getnext(const unordered_map<string,int> &id, string& a, vector<bool>& vis, vector<int> & res) {
        int len = a.size();
        for (int i = 0; i < len; i++) {
            char c = a[i];
            for (char t = 'a'; t < 'z'; t++) {
                if (t == c) continue;
                a[i] = t;
                auto it = id.find(a);
                if (it != id.end() && vis[it->second] == false) {
                    vis[it->second] = true;
                    res.push_back(it->second);
                }
            }
            a[i] = c;
        }
    }
};

 

你可能感兴趣的:(LeetCode)