[LeetCode] Word Ladder
Given two words (start and end), and a dictionary, find the length of shortest transformation sequence 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"]
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.
以下两种方法的思路几乎一样,但方法1:Time Limit Exceeded!方法2:Accept。
原因是:方法1找邻近字符串,是遍历dict中的每个字符串,对比两两字符串之间的每个字母,如果只有一个字母不同则视为neighbor,即代码中的isNeighbor()函数;方法2,是将一个字符串中的每个字母依次在‘a’-‘z’之间改变,即先得到neighbor字符串,然后查找这个字符串是不是在dict中。由于dict可能会非常大,而dict中的每个字符串的长度会比较小,所以用方法2的时间复杂度比较小。(即:Using isNeighbor seems to be slower than changing every position from 'a' to 'z'.)
方法1:
bool isNeighbor(string a,string b) { int diffNum = 0; bool res = true; for(int i=0;i<a.size();i++){ if(a[i]!=b[i] && ++diffNum != 1){ res = false; break; } }//end for return res; } class Solution { public: int ladderLength(string start, string end, unordered_set<string> &dict) { if(dict.size()<1) return 0; int num = 0; int len = start.size(); pair<string,int> pa(start,1);//key表示在寻找路径中出现的字符串,value表示此字符串是字符串组的第几个 queue<pair<string,int>> q; q.push(pa); num = bfs(dict,q,end); return num; } private: int bfs(unordered_set<string> &dict,queue<pair<string,int>> &q,string &end) { int curNum = 1; while(!q.empty()){ pair<string,int> pa = q.front(); q.pop(); string curS = pa.first; curNum = pa.second; if(curS == end) { break; } vector<string> BeDeleted; for(unordered_set<string>::iterator iter = dict.begin();iter != dict.end();iter++){ if(isNeighbor(*iter,curS)){ BeDeleted.push_back(*iter); pa = make_pair(*iter,curNum+1); q.push(pa); } }//end for for(int i=0;i<BeDeleted.size();i++) { dict.erase(BeDeleted[i]); } }//end while return curNum; } };
方法2:Accept
string NeighborIsInDict(queue<pair<string,int>> &q,unordered_set<string> &dict,string &curS,int &curNum,string &end) { string s(curS); int len = curS.size(); for(int i = 0;i<len;i++) { s = curS; for(int j=0;j<26;j++) { s[i]='a'+j; if(s==curS) continue; else if(s==end) { curNum++; return end; } else if(s!=curS && dict.count(s)) { dict.erase(s); q.push(make_pair(s,curNum+1)); } }//end for }//end for return s; } class Solution { public: int ladderLength(string start, string end, unordered_set<string> &dict) { if(dict.size()<1) return 0; int num = 0; int len = start.size(); pair<string,int> pa(start,1);//key表示在寻找路径中出现的字符串,value表示此字符串是字符串组的第几个 queue<pair<string,int>> q; q.push(pa); num = bfs(dict,q,end); return num; } private: int bfs(unordered_set<string> &dict,queue<pair<string,int>> &q,string &end) { int curNum = 0; while(!q.empty()){ pair<string,int> pa = q.front(); q.pop(); string curS = pa.first; curNum = pa.second; if(curS == end) { break; } string s0 = NeighborIsInDict(q,dict,curS,curNum,end); if(s0 == end) return curNum; }//end while return 0; } };