leetcode word ladder II

本文介绍了一种使用宽度优先搜索算法来寻找两个单词间的最短转换路径的方法,并通过改进算法避免了重复计算的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

  1. Only one letter can be changed at a time

  1. Each intermediate word must exist in the dictionary
给定两个单词,和一个词典,找出这两个单词间的所有最短转换,所有的中间转换单词都要在词典中。
由于求得是最短的路径 我们采用宽度优先搜索,当第一次找到的时候,就是最短的路径。

一开始的做法是,用一个队列实现宽度优先遍历,队列中存储着单词和到达这个单词的路径,每次遍历单词的临近单词,若其在词典中,将临近单词和临近单词的路径都压入队列中,但这样会产生超时的错误,因为同一个单词可能会被压入多次,进行了很多多余操作,虽然这不影响结果正确性,却消耗大量时间。

改进的算法,将所有到达某一单词的路径集中映射到单词中,即用hash表存储着所有到达某一单词的所有路径,队列中只存储着单词这个对象。
这此时不会产生多于的寻路。




class Solution {
public:
    bool istransfered(string a,string b){
        int len=a.length();
        int count=0;
       // cout<<a<<" "<<b<<endl;
        for(int i=0;i<len;i++){
            if(a[i]!=b[i]){
                if(count>0)
                    return false;
                count++;
            }
        }
        return true;
    }
    vector<vector<string>> findLadders(string start, string end, unordered_set<string> &dict) {
        queue<string> q;
        unordered_map<string,vector<vector<string>>>mq;
        vector<vector<string>>res;
        unordered_map<string,int> m;
        int length=start.size();
        m[start]=0;
        auto it=dict.find(end);
        if(it!=dict.end()){
        	dict.erase(it);
        }
        it=dict.find(start);
        if(it!=dict.end()){
        	dict.erase(it);
        }
       // dict.insert(end);
        q.push(start);
        mq[start].push_back(vector<string>(1,start));
        bool hasfind=false;
        int step;
        while(!q.empty()){
            string cur=q.front();
            vector<vector<string>> &paths=mq[cur];
            q.pop();
            if(hasfind){
                if(paths[0].size()>=step)
                    continue;
            }
            if(istransfered(cur,end)){
            	//std::cout<<cur<<" "<<end<<" size"<<paths[0].size()<<std::endl;
                if(!hasfind){
                	for(int i=0;i<paths.size();i++){
                		paths[i].push_back(end);
                		res.push_back(paths[i]);
                		
                	}
                	hasfind=true;
                	step=paths[0].size();
                }
                else{
                    if(paths[0].size()>=step){
                        continue;
                        
                        
                    }
                    
                	for(int i=0;i<paths.size();i++){
                		paths[i].push_back(end);
                		res.push_back(paths[i]);
                		
                	}
                	if(paths[0].size()<step){
                	    return res;
                	}
                }
                continue;
            }
            auto iter=dict.begin();
            //vector<vector<string >> &paths=mq[cur];
            string curword=cur;
            for(int i=0;i<length;i++){
            	for(char c='a';c<='z';c++){
            		if(cur[i]==c){
            			continue;
            		}
            		curword[i]=c;
            		
            		auto iter=dict.find(curword);
            		if(iter!=dict.end()){
            		
            		auto iit=m.find(curword);
            		if(iit!=m.end()){
            		if(m[curword]<paths[0].size()){
            			continue;
            		}
            		
            		}
            		else{q.push(*iter);}
                    	//cout<<cur<<"  "<<*iter<<endl;
                    	//cout<<paths.size()<<endl;
                   	 	m[*iter]=paths[0].size();
                   	 	
                    	for(int i=0;i<paths.size();i++){
                    		paths[i].push_back(*iter);
                    		mq[*iter].push_back(paths[i]);
                    		paths[i].pop_back();
                    	}
            		}
            	}
            	curword[i]=cur[i];
            	
            }
        
        }
        return res;
    }
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值