单词接龙2


和上一个单词接龙不一样在,这道题返回所有的最短路径

记录搜索路径的宽搜:

1.将普通队列更换为vector,保存所有的搜索结点,在pop时不会丢弃队头元素,只是移动front指针

2.在队列结点中增加该结点的前驱结点在队列中的下标信息,可通过该下标找到是从队列中的哪个结点搜索到当前结点的

多条路径的保存:

到达某一位置可能存在多条路径,使用映射记录到达每个位置的最短需要步数,新拓展到的位置只要未曾到达或到达步数与最短步数相同,即将该位置添加到队列中,从而存储了从不同前驱到达该位置的情况

struct item{
    string node;
    int pre_pos;
    int step;
    item(string _node,int _pre_pos,int _step):node(_node),pre_pos(_pre_pos),step(_step){}
};

class Solution {
public:
    bool connect(string& s1,string& s2)
    {
        int cnt = 0;
        for(int i =0;i<s1.size();++i)
        {
            if(s1[i]!=s2[i])
                cnt++;
        }
        return cnt == 1;
    }
    
    
    //构建图与单词接龙1有一些不一样,因为上一题是求出最短步数就行,而这一题需要求出所有的最短路径
    //如果wordlist里面有了beginword,我们又push了一个beginword进去,就会有重复路径
    void construct_graph(string& beginword,vector<string>& wordlist,map<string,vector<string> >& graph)
    {
        int has_beginword = 0;
        for(int i =0;i<wordlist.size();++i)
        {
            if(wordlist[i] == beginword)
                has_beginword = 1;
            graph[wordlist[i]] = vector<string>();
        }
        
        for(int i =0;i<wordlist.size();++i)
        {
            for(int j = i+1;j<wordlist.size();++j)
            {
                if(connect(wordlist[i],wordlist[j]))
                {
                    graph[wordlist[i]].push_back(wordlist[j]);
                    graph[wordlist[j]].push_back(wordlist[i]);
                }
            }
            if(has_beginword == 0 && connect(wordlist[i],beginword))
            {
                graph[wordlist[i]].push_back(beginword);
                graph[beginword].push_back(wordlist[i]);
            }
        }
    }
                                                                                 //队列,          终点单词所在队列的位置下标
    void BFS(string& beginword,string& endword,map<string,vector<string> >& graph,vector<item>& q,vector<int>& end_word_pos)
    {
        map<string,int> visit;//<单词,步数>
        int min_step = 0;
        q.push_back(item(beginword,-1,1));//起始单词的前驱为-1
        visit[beginword] = 1;
        int front = 0;//队列头指针
        
        while(front != q.size())
        {
            string node = q[front].node;
            int step = q[front].step;
            
            if(min_step != 0  &&  step > min_step)//step > min_step代表所有到终点的路径都搜索完成
                break;
            
            if(node == endword)
            {
                min_step = step;//搜索到结果时,记录到达终点
                end_word_pos.push_back(front);
            }
            
            vector<string> neighbors = graph[node];
            
            for(int i =0;i<neighbors.size();++i)
            {   //结点没被访问,或是另一条最短路径
                if(visit.find(neighbors[i]) == visit.end()  || visit[neighbors[i]] == step+1)
                {
                    q.push_back(item(neighbors[i],front,step+1));
                    visit[neighbors[i]] = step + 1;
                }
            }
            front++;
        }
    }
    
    
    
    vector<vector<string>> findLadders(string beginWord, string endWord, vector<string>& wordList) {
        map<string,vector<string> > graph;
        vector<item> q;
        vector<int> end_word_pos;
        
        construct_graph(beginWord,wordList,graph);
        BFS(beginWord,endWord,graph,q,end_word_pos);
        
        vector<vector<string> > res;
        //保存路径结果
        for(int i = 0;i<end_word_pos.size();++i)
        {
            int pos = end_word_pos[i];
            vector<string> path;//从后向前保存路径,之后再反过来存入到res中
            while(pos != -1)
            {
                path.push_back(q[pos].node);
                pos = q[pos].pre_pos;
            }
            res.push_back(vector<string>());
            
            for(int j = path.size() -1 ;j>=0;--j)
                res[i].push_back(path[j]);
        }
        
        return res;
    }
};

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值