Word Ladder II

题目描述:

Given two words (beginWord and endWord), and a dictionary's word list, find all shortest transformation sequence(s) from beginWord toendWord, such that:

  1. Only one letter can be changed at a time
  2. Each intermediate word must exist in the word list

For example,

Given:
beginWord = "hit"
endWord = "cog"
wordList = ["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.
解题思路:

首先按照宽度优先建立从字符串start每次变化一个字符直到字符串end的图,
然后从start到end的所有路径即为所求的结果。


在宽度优先建立从字符串start每次变化一个字符直到字符串end的图的过程使用两个集合,
分别保存当前阶段和下一阶段的字符串的集合。对于当前阶段的字符串集合的处理包括两个步骤:
(1)对于当前阶段的字符串集合首先把它们从输入字符串字典中删除
(2)下一阶段的字符串的集合由当前阶段的字符串集合中的字符串变化一个字符得到。
当前阶段的字符串集合初始化只包含start字符串。


AC代码如下:

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)
		{//宽度优先建立从字符串start每次变化一个字符直到字符串end的图
			current = !current;
			previous = !previous;
			//1.从输入字符串字典中删除当前阶段的字符串
			for (auto iter = candidates[previous].begin(); iter != candidates[previous].end(); ++iter)
				dict.erase(*iter);
			candidates[current].clear();
			//2.下一阶段的字符串的集合由当前阶段的字符串集合中的字符串变化一个字符得到
			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);
						}
					}
				}
			}
			//如果下一阶段的字符串集合为空,即无法建立从start到end的图
			if (candidates[current].size() == 0)
				return result_;
			//如果已经到达字符串end,则建图过程结束
			if (candidates[current].count(end)) break;
		}
		vector<string> path;
		//深度优先遍历找到从字符串start到字符串end的路径
		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)  //ie. reach the start word
		{
			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_;
};


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值