采用分治法的思想。
(1)把所有两数之和计算出来,并保存在multimap中。放在unordered_multimap中的效率更高,但是因为其采用hash定位元素的方法,导致map中的数据不能按序索引。故要放弃unordered,虽然在有的版本中unordered的某些类型可以保持一定顺序,但本质是无序的。
(2)对关联容器进行删除操作后,迭代器就会失效。这个一定要注意。例如:auto p = mmp.equal_range(val) ,此时如果对p.first和p.second之内的迭代器进行删除,那么下次的p就要重新计算。
(3)此题可用trie树加以优化,后话。
<span style="font-size:14px;">vector<vector<string>> findLadders(string start, string end, unordered_set<string> &dict) {
vector<vector<string>> res; vector<string> path;
if(!dict.size()) return res;
queue<string> q; int minLen=10000;int len;string ss;
unordered_map<string,int> mp; unordered_multimap<string,string> parent;
dict.insert(end);
if(dict.count(start)) dict.erase(start); q.push(start); mp[start]=1;
parent.insert(make_pair(start,""));
while(!q.empty()){
auto str = q.front(); q.pop();
for(auto i=0 ; i< str.size(); ++i){
auto tmp=str;
//auto p= parent.equal_range(str); <strong>//if we put p here ,then will get RE, because p are invalid after erase operation!!</strong>
for(char j='a';j<='z';++j){
tmp[i]=j; //bool f=false;//cout<<tmp<<endl;
/*auto p= parent.equal_range(str); <strong>// update p everytime an erase ocur</strong>
for(auto t=p.first;t!=p.second;++t)
if(t->second==tmp) f=true;
if(f) break;*/
if ( str[i]!=j && dict.count(tmp) ) {
if(tmp==end){
len = mp[str]+1;
minLen = min(len,minLen);
if(len>minLen) continue;
if(len==minLen){
path.clear();
ss=str;
path.push_back(end);
while(ss!="") {
path.push_back(ss);
auto it=parent.find(ss);<span style="white-space:pre"> </span><strong>//change it to multimap, ok but low efficient</strong>
auto cnt=parent.count(ss);
ss=it->second;
if(cnt>1) parent.erase(it); <strong>// wrong! elements in this is unordered, you should reley on this</strong>
}
res.push_back(path);
}
}
else{
if(mp[str]+1<minLen) {
if(parent.find(tmp)!=parent.end() && mp[str]+1 != mp[tmp] ) continue;
mp[tmp]=mp[str]+1;
q.push(tmp);
parent.insert(make_pair(tmp,str));
}
}
}
}
}
}cout<<res.size()<<endl;
for(auto &vec:res)
reverse(vec.begin(),vec.end());
return res;
}</span>
如果改成multimap效率就会大打折扣,但是寻找父亲节点必须依赖循序性。如果想用unordered,唯一的办法是在此过程不用map,办法是有的:represent paths as string。如下:
vector<vector<string>> findLadders(string start, string end, unordered_set<string> &dict) {
vector<vector<string>> res;
if(!dict.size()) return res;
int minLen=10000,len;string ss,road,tmpRoad;
vector<string> paths,vtmp;
queue<string> q,path;
unordered_map<string,int> mp;
unordered_map<string,string> parent;
dict.insert(end);dict.erase(start); q.push(start); mp[start]=1;
path.push(start);parent.insert(make_pair(start,""));
while(!q.empty()){
auto str(q.front()); q.pop();//cout<<"*" << str;
<strong>auto road(path.front());path.pop();</strong>//cout<<road<<endl;
for(auto i=0 ; i< str.size(); ++i){
auto tmp(str);
for(char j='a';j<='z';++j){
tmp[i]=j; tmpRoad= road;
if ( str[i]!=j && dict.find(tmp)!=dict.end() ) { //cout<<tmp<<endl;
if(tmp==end){
len = mp[str]+1;//cout<<str<<endl;cout<<len<<endl;
minLen = min(len,minLen);//cout<<minLen<<endl;
if(len>minLen) continue;
if(len==minLen){
<strong>tmpRoad +=end;
paths.push_back(tmpRoad);</strong>
}
}
else{
if(mp[str]+1<minLen) {
if(parent.find(tmp)!=parent.end() && mp[str]+1 != mp[tmp] ) continue;
mp[tmp]=mp[str]+1;//cout<<"["<< tmp<<"]";
q.push(tmp);
<strong>tmpRoad +=tmp;
path.push(tmpRoad);</strong>
parent.insert(make_pair(tmp,str));
}
}
}
}
}
}//cout<<res.size()<<endl;
//for(auto p:paths)
//cout<<p<<endl;
for(auto &p:paths){
vtmp.clear();
for(int i=0 ; i<p.size()-2;i=i+3)
vtmp.push_back(p.substr(i,3));
res.push_back(vtmp);
}
return res;
}
虽然如此,效率还是不行,如何改进且待下回分解。