LeetCode OJ 之 Word Ladder II (字梯 - 二)

题目:

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
  2. Each intermediate word must exist in the dictionary

给定两个单词(start 和 and ),以及一个字典,找出从 start 到 end 最短变换序列的长度。

1、一次只能改变一个字母。

2、每个中间词必须在字典中存在。

For example,

Given:
start = "hit"
end = "cog"
dict = ["hot","dot","dog","lot","log"]

Return

  [
    ["hit","hot","dot","dog","cog"],
    ["hit","hot","lot","log","cog"]
  ]

Note:

  • All words have the same length.
  • All words contain only lowercase alphabetic characters.

思路:

先参考这个:http://blog.csdn.net/u012243115/article/details/41645063 。本题需要求出找到的所有路径,而链接的那一题只需要求出路径长度即可。

参考:http://www.tuicool.com/articles/eaQNNr 。

本题可以通过上一题的思路构造一个邻接表表示的图,对于题目给出的例子,可以构造如下图(图与题目给的数据有出入,大家明白那个意思就行了),图的数据结构我们可以用unorder_map<string,unordered_set<string>> graph 来表示:


然后用DFS遍历图,即可构造出路径。但是这样的图遍历会遍历到很多无用的路径,比如hot->hop ,或者 hot->pop 等,于是我们可以想到从下到上遍历,即从end找start,这样一定可以找到要求的正确路径,不需要遍历那些无用的路径。这样我们可以在用BFS构造图的时候构造一个反向邻接表,这样方便遍历。如下所示:

dog--->dot, hog

cog--->hog

hop--->hot

tot--->hot

dot--->hot

pot--->hot

hog--->hot

代码:

class Solution {
public:
    vector<string> tmpPath;//用于构造当前路径
    vector<vector<string> > result;//保存结果,即所有的路径
    vector<vector<string>> findLadders(string start, string end, unordered_set<string> &dict)
    {
        unordered_set<string> curLevel;//当前层次单词集合,也可以用vector<string>来表示,但是这个查找时候要用find函数
        unordered_set<string> nextLevel;//下一层单词集合
        unordered_set<string> unvisited(dict);//还未访问的结点
        unordered_map<string,unordered_set<string> > graph;//图,反向邻接表
        
        if(unvisited.count(start) != 0) //先清空unvisited中的start
            unvisited.erase(start);
        curLevel.insert(start);//第一层就一个单词start
        
        //循环结束条件是找到end或者所有单词都遍历完了
        while(curLevel.count(end) == 0 && unvisited.size() > 0)
        {
            //遍历当前层次的单词,找到下一层的单词,并构造图
            for(auto iter = curLevel.begin() ; iter != curLevel.end() ; iter++)
            {
                string curWord = *iter;//当前层次的单词
                for(int i = 0 ; i < start.size() ;i++)
                {
                    for(char c = 'a' ; c < 'z' ; c++)
                    {
                        string tmp = curWord;
                        if(tmp[i] == c)
                            continue;
                        tmp[i] = c;
                        //如果找到,则插入下一层中,并且在图中构造tmp->word
                        if(unvisited.count(tmp) > 0)
                        {
                            nextLevel.insert(tmp);
                            graph[tmp].insert(curWord);//反向构造图,即下一层的单词指向上一层
                        }
                    }
                }
            }
            if(nextLevel.empty())
                break;
            //当前层次遍历完,把下一层的单词从unvisited中删除
            for(auto iter = nextLevel.begin() ; iter != nextLevel.end() ; iter++)
            {
                unvisited.erase(*iter);
            }
            curLevel = nextLevel;
            nextLevel.clear();
        }
        //如果当前层次上存在end,说明找到了路径,则用DFS从下向上构造路径
        if(curLevel.count(end) > 0)
            DFS_GenPath(graph,end,start);
        return result; 
    }
    void DFS_GenPath(unordered_map<string,unordered_set<string> > &graph , string start , string end)
    {
        tmpPath.push_back(start);
        if(start == end)
        {
            vector<string> tmp = tmpPath;
            reverse(tmp.begin() , tmp.end());
            result.push_back(tmp);
            return;
        }
        for(auto iter = graph[start].begin() ; iter != graph[start].end() ; iter++)
        {
            DFS_GenPath(graph,*iter,end);
            tmpPath.pop_back();
        }
    }
};



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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值