Word Ladder II

本文介绍了一道LeetCode题目——寻找两个单词之间的最短转换路径,详细解析了使用广度优先搜索策略求解的方法,并阐述了如何通过递归方式获取所有最短转换序列。

leetcode: 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

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.
解题思路:
1、使用图的广度优先搜索策略(BFS);
2、由于要返回所有的最短转换序列,使用unordered_map<string , vector<string>>来存储每个节点的前驱节点;
3、使用递归的形式,将unordered_map<string , vector<string>>中存放的节点顺序信息恢复成转换序列。
代码:
class Solution {
private:
        vector> pathes;
        void buildPathes(unordered_map> &traces , vector &path , const string end)
        {
            if(traces[end].size() == 0)
            {
                path.push_back(end);
                vector curPath = path;
                reverse(curPath.begin() , curPath.end());
                pathes.push_back(curPath);
                path.pop_back();
                return;
            }
            vector prevs = traces[end];
            path.push_back(end);
            for(vector::iterator it = prevs.begin() ; it != prevs.end() ; it++)
            {
                buildPathes(traces , path , *it);
            }
            path.pop_back();
        }
public:
    vector> findLadders(string start, string end, unordered_set &dict) {
        pathes.clear();
        dict.insert(start);
        dict.insert(end);
        vector prev;
        unordered_map> traces;
        for(unordered_set::iterator it = dict.begin() ; it != dict.end() ; it++)
        {
            traces[*it] = prev;
        }
        vector> layer(2);
        bool cur = true;
        bool pre = false;
        layer[cur].insert(start);
        while(true)
        {
            cur = !cur;
            pre = !pre;
            for(unordered_set::iterator it = layer[pre].begin(); it != layer[pre].end() ; it++)
            {
                dict.erase(*it);
            }
            layer[cur].clear();
            
            for(unordered_set::iterator it = layer[pre].begin(); it != layer[pre].end() ; it++)
            {
                for(int i = 0 ; i < (*it).size() ; i++)
                {
                    string word = *it;
                    int stop = word[i] - 'a';
                    for(int c = (stop + 1)%26 ; c != stop ; c = (c + 1)%26)
                    {
                        word[i] = c + 'a';
                        if(dict.find(word) != dict.end())
                        {
                            traces[word].push_back(*it);
                            layer[cur].insert(word);
                        }
                    }
                }
            }
            if(layer[cur].size() == 0)
                return pathes;
            if(layer[cur].count(end))
                break;
        }
        vector path;
        buildPathes(traces, path, end);
        return pathes;
    }
};
疑点:根据unordered_map<string , vector<string>>中的节点信息,从end节点开始,递归往前推导,得出来的转换序列是全部转换序列,还是所有最短转换序列?答案肯定是返回所有的最短转换序列,首先可以这样想,在广度优先搜索的时候,Layer[pre]和Layer[cur]像剥洋葱一样,一层一层的向前推进,直到搜索到单词end的时候结束,那么从end再一层一层返回,得到的也会是最短的转换序列。换一种思路,假设在原单词表中,单词a可以直接到单词x,即a -> x,也可以经过单词b到单词x,即a -> b -> c ->x。当{a}为当前所搜索的层次时,记录x的前驱是a,b的前驱是a,所以,接下来搜索的一层是{b , x},然后在单词表中删除b、x,由此可以得出,b -> c -> x这个路径是记录不下来的。所以,广度优先搜索记录下来的路径是最短路径。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值