Word Ladder I && II

(1) Word Ladder I

BFS(宽度优先搜索),但是我们可以假想构建一个图,其中图中的每个顶点都是我们的元素,点和点是如何联系起来的呢?如果一个单词通过改变一次字母,能够变成另外一个单词,我们称之为1 edit distance 距离(是不是想起了leetcode中edit distance那道题目了?)所以,图中的所有相邻元素都是edit distance 距离为1的元素。那么,我们只需要做BFS,哪里最先遇到我们的target word,那么我们的距离就是多少。如果遍历完所有的元素都没有找到target word,那么我们就返回1。[1]

class Solution {

public:
    int ladderLength(string start, string end, unordered_set<string> &dict) {
        if(start==end)
            return 1;
            
        queue<string> neighbor,curque;
        int distance=1;
        curque.push(start);
        
        while(dict.size()>0 && !curque.empty())
        {
            
            while(!curque.empty())
            {
                string cur(curque.front());
                curque.pop();
                for(int i=0;i<start.size();i++)
                    for(char j='a';j<='z';j++)
                    {
                        string tmp(cur);
                        tmp[i]=j;
                        
                        if(tmp==end)
                            return distance+1;
                            
                        if(dict.count(tmp)>0)
                        {
                            neighbor.push(tmp);
                            dict.erase(tmp);
                        }
                    }
            }
            distance++;
            swap(neighbor,curque);
        }
        return 0;
    }
};

(2) Word Ladder II

使用了一个前驱单词表,即记录每一个单词的前驱单词是哪些。这样先bfs遍历完毕后,我们从end出发dfs递归就能把所有路径生成出来。[2]

class Solution {
private:
    vector<vector<string>> ret;
    bool bfs(string start,string end,unordered_map<string, vector<string>> &premap,unordered_set<string> &dict) {
        for(auto iter = dict.begin(); iter != dict.end(); ++iter)
            premap[*iter] = vector<string>();
        vector<unordered_set<string>> candidates(2);
        int current = 0;
        int previous = 1;
        candidates[current].insert(start);
        
        while(true)
        {
            current = !current;
            previous = !previous;
            for (auto iter = candidates[previous].begin(); iter != candidates[previous].end(); ++iter)
                dict.erase(*iter);
            candidates[current].clear();
            for(auto iter = candidates[previous].begin(); iter != candidates[previous].end(); ++iter)
            {
                for(int i=0;i<start.size();i++)
                {
                    string tmp(*iter);
                    for(char j='a';j<='z';j++)
                    {
                        if(tmp[i]==j)
                            continue;
                        tmp[i]=j;
                            
                        if(dict.count(tmp)>0)
                        {
                            if(candidates[current].count(tmp)==0)
                                candidates[current].insert(tmp);
                            premap[tmp].push_back(*iter);
                        }
                    }
                }
            }
            if (candidates[current].size() == 0)
                return true;
            if (candidates[current].count(end)) break;
        }
        return false;
    }
    
    void dfs(string &cur,vector<string> &tmp,unordered_map<string, vector<string>> &premap) {
        if(premap[cur].size()==0)
        {
            tmp.push_back(cur);
            vector<string> curPath = tmp;
            reverse(curPath.begin(),curPath.end());
            ret.push_back(curPath);
            tmp.pop_back();
            return;
        }
        
        tmp.push_back(cur);
        for(auto iter=premap[cur].begin();iter != premap[cur].end(); iter++)
            dfs(*iter,tmp,premap);
        tmp.pop_back();
    }
    
public:
    vector<vector<string>> findLadders(string start, string end, unordered_set<string> &dict) {
        
        ret.clear();
        unordered_map<string, vector<string>> premap;
        
        if(bfs(start,end,premap,dict))
            return ret;
        
        vector<string> tmp;
        dfs(end,tmp,premap);
        return ret;
    }
};
注意参数尽可能用引用传值,不然递归的时候可能会内存溢出。


参考:

[1] http://blog.csdn.net/zxzxy1988/article/details/8591890

[2] http://blog.csdn.net/doc_sgl/article/details/13341405

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值