word ladder 2 的复杂实现

采用分治法的思想。

(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;
    }
虽然如此,效率还是不行,如何改进且待下回分解。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值