126. Word Ladder I & II

一、题目简述

给定两个单词(beginWord和endWord),和一个单词字典,找到所有从beginWord到endWord的最短转换,使得:

  1. 每次只能改变一个字母;
  2. 每个转换单词都必须在单词字典中,注意到,beginWord不是一个转换单词。

例如,
给定:
beginWord=“hit”
endWord=“cog”
wordList=[“hot”,”dot”,”dog”,”lot”,”log”,”cog”]
返回:
[
[“hit”,”hot”,”dot”,”dog”,”cog”],
[“hit”,”hot”,”lot”,”log”,”cog”]
]
注意到:

  • 如果不存在满足条件的转换序列,则返回空列表。
  • 所有的单词都有相同的长度
  • 所有的单词都只包含小写的阿拉伯字符
  • 假设列表中没有重复单词
  • 假设beginWord和endWord非空,并且不相同

函数原型:
int strDiff(string str1,string str2)

二、编程思路

Word Ladder I&II的思路类似,只是I只需要返回最短转化路径的长度,而II则需要返回所对应的路径。对于类似的最短转化次数的问题,一般都可以采用宽度优先搜索BFS的思路。将beginWord作为搜索起点,endWord为搜索终点。对于WordList列表中的单词,使用下标表示每个字符串,并且使用邻接表记录每个单词能够经过一次转化就得到单词的下标。

由于需要返回相应的路径,因此还需要使用一个队列记录从beginWord转换到当前单词的路径。

为了避免重复的搜索,可以记录每个单词是否被访问过,使用逐层的BFS,对于下一层,都不在访问上一层已经访问过的单词。

三、代码设计

class Solution {
public:
    int strDiff(string str1,string str2){
        int len=min(str1.length(),str2.length());
        int ans=0;
        ans+=abs(str1.length()-str2.length());
        for(int i=0;i<len;i++){
            if(str1[i]!=str2[i]) ans++;
        }
        return ans;
    }
    vector<vector<string>> findLadders(string beginWord, string endWord, vector<string>& wordList) {
        int num=wordList.size();
        vector<vector<int> >adjList,idx_ans;
        vector<vector<string> >str_ans;
        //检查endWord是否在wordList中
        bool end_flag=true,begin_flag=true;
        int end_idx=0,begin_idx=0;
        for(int i=0;i<num;i++){
            if(strDiff(endWord,wordList[i])==0){
                end_flag=false;
                end_idx=i;
            }
            if(strDiff(beginWord,wordList[i])==0){
                begin_flag=false;
                begin_idx=i;
            }

        }
        if(end_flag) return str_ans;
        if(begin_flag){
            wordList.insert(wordList.begin(),beginWord);
            num++;
            end_idx++;
        }
        //计算每个单词的邻接单词
        for(int i=0;i<num;i++){
            vector<int> tmp;
            for(int j=0;j<num;j++){
                if((1==strDiff(wordList[i],wordList[j]))){
                    tmp.push_back(j);
                }
            }
            adjList.push_back(tmp);
        }        
        //进行广度优先搜索
        queue<int> q;
        queue<vector<int> >status;
        q.push(begin_idx);
        status.push(vector<int>(1,begin_idx));
        vector<bool> is_visit(num,false);
        is_visit[begin_idx]=true;
        int min_len=num;
        bool end_loop=false;        
        while(!q.empty()){
            int q_size=q.size();
            vector<int>visit_idx;
            //逐层搜索
            for(int i=0;i<q_size;i++){
                int cur=q.front(); q.pop();
                vector<int> cur_st=status.front(); status.pop();
                if(cur_st.size()>min_len){
                    end_loop=true;
                    continue;
                }
                //找到了endWord的情况
                if(cur==end_idx){
                    idx_ans.push_back(cur_st);
                    min_len=cur_st.size();
                    end_loop=true;
                    continue;
                }
                for(int j=0;j<adjList[cur].size();j++){
                    if(!is_visit[adjList[cur][j]])
                    {
                        vector<int> tmp_st(cur_st);
                        tmp_st.push_back(adjList[cur][j]);
                        // cout<<adjList[cur][j]<<" ";
                        q.push(adjList[cur][j]);
                        visit_idx.push_back(adjList[cur][j]);
                        status.push(tmp_st);
                    }
                }

            }
            for(int j=0;j<visit_idx.size();j++){
                    is_visit[visit_idx[j]]=true;
                }
            if(end_loop) break;
        } 
        for(int i=0;i<idx_ans.size();i++){
            vector<string> tmp;
            for(int j=0;j<idx_ans[i].size();j++){
                tmp.push_back(wordList[idx_ans[i][j]]);
            }
            str_ans.push_back(tmp);
        }
        return str_ans;
    }
};

四、参考资料

使用此种方法,思路简单,但较为耗时。可以参考题解中使用双向BFS缩小算法的时间。
126. Word Ladder II题解

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值