Monday, November 25, 2013

LeetCode Problem : Word Ladder II

Problem



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

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

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

Code

bool isConv(const std::string& s1,const std::string& s2)
{
    int diff = 0;
    int m = s1.size();
    int n = s2.size();
    if(m != n)
        return false;
    for(int i = 0; i < n; ++i){
        if(s1[i] != s2[i])
            ++diff;
        if(diff > 1)
            return false;
    }
    if(diff == 0)
        return false;
    return true;
}
bool inDict(string start,unordered_set<string> &dict)
{
    std::unordered_set<std::string>::const_iterator got = dict.find (start);
    return ( got != dict.end() );
}
vector<string> getWords(string start,unordered_set<string> &dict)
{
    int n = start.size();
    vector<string> result;
    for(int i = 0;i < n; ++i){
        string temp = start;
        for(int j = 0;j < 26; ++j){
            if(start[i] != 'a' + j){
                temp[i] = 'a' + j;
                if(inDict(temp,dict)){
                    result.push_back(temp);
                }
            }
        }
    }
    return result;
}
int findLaddersBFS(std::string start, std::string end, std::unordered_set<std::string> &dict
,map<string,int>& level_num,map<string,set<string> >& pi) {
    for (auto itr = dict.begin(); itr != dict.end(); ++itr) {
        level_num[*itr] = INT_MAX;
    }
    level_num[start] = 1;
    level_num[end] = INT_MAX;
    deque<string> Q;
    Q.push_back(start);
    while(!Q.empty()){
        string v = Q.front();
        Q.pop_front();
        int v_level = level_num[v];
        int end_level = level_num[end];
        if(v_level >= end_level)
        return end_level;
        vector<string> words = getWords(v,dict);
        vector<string>::iterator it = words.begin();
        for(; it != words.end(); ++it){
            string w = *it;
            int w_level = level_num[w];
            if(w_level >  v_level + 1){
                pi[w].insert(v);
                level_num[w] = v_level + 1;
                if(w_level < end_level && isConv(w,end)){
                    level_num[end] = v_level + 2;
                    pi[end].insert(w);
                }
                else
                    Q.push_back(w);
            }
            else if(w_level ==  v_level + 1){
                pi[w].insert(v);
                if(w_level < end_level && isConv(w,end)){
                    pi[end].insert(w);
                }
            }
        }
    }
    return 0;
}
void printPi( map<string,set<string> >& pi,const string& end,const string& start,vector<string>& out,
             int pos,vector<vector<string>>& result){
    out[pos] = end;
    if(start == end){
        result.push_back(vector<string>(out.rbegin(),out.rend()));
        return;
    }
    set<string> parents = pi[end];
    set<string>::iterator it = parents.begin();
    for(;it != parents.end(); ++it){
        printPi(pi,*it,start,out,pos + 1,result);
    }
}
vector<vector<string>> findLadders(string start, string end, unordered_set<string> &dict) {
    // IMPORTANT: Please reset any member data you declared, as
    // the same Solution instance will be reused for each test case.
    vector<vector<string>> result;
    if(isConv(start,end)){
        vector<string> tmp(2);
        tmp[0] = start;
        tmp[1] = end;
        result.push_back(tmp);
        return result;
    }
    map<string,int> level_num;
    map<string,set<string> > pi;
    int endl_level = findLaddersBFS(start,end,dict,level_num,pi);
    if(endl_level == 0)
        return result;
    vector<string> out(endl_level);
    printPi(pi,end,start,out,0,result);
    return result;
}


No comments:

Post a Comment