【LeetCode】word ladder I&& II

参考链接


http://www.cnblogs.com/x1957/p/3274819.html

http://www.cnblogs.com/x1957/p/3526838.html






题目描述

Word Ladder

 

Given two words (start and end), and a dictionary, find the length of shortest transformation sequence 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"]

As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog",
return its length 5.

Note:

  • Return 0 if there is no such transformation sequence.
  • All words have the same length.
  • All words contain only lowercase alphabetic characters.

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

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.



题目分析

I 思路应该是按层遍历,字典中与某个单词只有一个字母之差的都是这个字母的孩子,构建一棵树,再按层遍历,遍历到目标单词时的层数就是转换次数。

II 需要记录每一个孩子的父亲结点,注意的事,父亲不只有一个。

总结


代码示例

int ladderLength(string start, string end, unordered_set<string> &dict) {
        // IMPORTANT: Please reset any member data you declared, as
        // the same Solution instance will be reused for each test case.
		if(start.size() != end.size()) return 0;
		if(start.empty() || end.empty())return 0;
		
		queue<string> path;
		path.push(start);
		int level = 1;
		int count = 1;
		dict.erase(start);
		while(dict.size() > 0 && !path.empty())
		{
			string curword = path.front();
			path.pop();count--;
			for(int i = 0; i < curword.size(); i++)
			{
				string tmp = curword;
				for(char j='a'; j<='z'; j++)
				{
					if(tmp[i]==j)continue;
					tmp[i] = j;
					if(tmp==end)return level+1;
					if(dict.find(tmp) != dict.end()) path.push(tmp);
					dict.erase(tmp);
				}
			}
			if(count==0)
			{
				count = path.size();
				level++;
			}
		}
		return 0;
    }


class Solution {
public:
    int ladderLength(string start, string end, unordered_set<string> &dict) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        if(start == end) return 1;
        queue<string > que;
        map<string , int> dist;
        dist[start] = 0;
        que.push(start);
        while(!que.empty()){
            string top = que.front();que.pop();
            for(int i = 0 ; i < top.length() ; i++){
                for(int j = 'a' ; j <= 'z' ; j++){
                    if(j != top[i]){
                        string next = top;
                        next[i] = j;
                        if(next == end){
                            return dist[top] + 2;
                        }
                        if(dict.find(next) != dict.end() && dist.find(next) == dist.end()){
                            dist[next] = dist[top] + 1;
                            que.push(next);
                        }
                    }
                }
            }
        }
        return 0;
    }
};








class Solution {
public:
    vector<vector<string> > findLadders(string start, string end, unordered_set<string> &dict)
    {
        result_.clear();
        unordered_map<string, vector<string>> prevMap;
        for(auto iter = dict.begin(); iter != dict.end(); ++iter)
            prevMap[*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(size_t pos = 0; pos < iter->size(); ++pos)
                {
                    string word = *iter;
                    for(int i = 'a'; i <= 'z'; ++i)
                    {
                        if(word[pos] == i)continue;
                        word[pos] = i;
                        if(dict.count(word) > 0)
                        {
                            prevMap[word].push_back(*iter);
                            candidates[current].insert(word);
                        }
                    }
                }
            }
            if (candidates[current].size() == 0)
                return result_;
            if (candidates[current].count(end)) break;
        }
        vector<string> path;
        GeneratePath(prevMap, path, end);
        return result_;
    }
    
private:
    void GeneratePath(unordered_map<string, vector<string>> &prevMap, vector<string>& path, const string& word)
    {
        if (prevMap[word].size() == 0)
        {
            path.push_back(word);
            vector<string> curPath = path;
            reverse(curPath.begin(), curPath.end());
            result_.push_back(curPath);
            path.pop_back();
            return;
        }
        path.push_back(word);
        for (auto iter = prevMap[word].begin(); iter != prevMap[word].end(); ++iter)
            GeneratePath(prevMap, path, *iter);
        path.pop_back();
    }
    vector<vector<string>> result_;
};

class Solution {
public:
    vector<vector<string>> findLadders(string start, string end, unordered_set<string> &dict) {
          vector<vector<string> >ans;
          if(start == end) return ans;
          unordered_set<string>current , next;
          unordered_set<string> flag;
          unordered_map<string,vector<string> > father;
          
          current.insert(start);

          bool found = false;
         
          while(!current.empty() && !found) {
              //expand
              for(const auto &x : current) {
                  flag.insert(x);
              }
              
              for(auto x : current) {
                  for(int i = 0 ; i < x.size() ; ++i) {
                      for(int j = 'a' ; j <= 'z' ; ++j) {
                          if(x[i] == j) continue;
                          string tmp = x;
                          tmp[i] = j;
                          if(tmp == end) found = true;
                          if(dict.find(tmp) != dict.end() && flag.find(tmp) == flag.end()) {
                              next.insert(tmp);
                              father[tmp].push_back(x);
                          }
                     }
                  }
              }
              //end expand
              
              current.clear();
              swap(current, next);
          }
          //start foudn father
          
          if(found) {
              vector<string> c;
              dfs(ans , father , c , start , end);
          }
          return ans;
    }
private:
    void dfs(vector<vector<string> >&ans, 
             unordered_map<string,vector<string> >& father ,
             vector<string>& c , 
             string& start ,
             string& now) {
                 
        c.push_back(now);
        if(now == start) {
            ans.push_back(c);
            reverse(ans.back().begin() , ans.back().end());
            c.pop_back();
            return;
        }
        auto que = father.find(now) -> second;
        for(auto& x : que) {
            dfs(ans , father , c , start , x);
        }
        c.pop_back();
    }
};



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值