力扣第126题单词接龙II,bfs

  1. 单词接龙 II

给定两个单词(beginWord 和 endWord)和一个字典 wordList,找出所有从 beginWord 到 endWord 的最短转换序列。转换需遵循如下规则:

每次转换只能改变一个字母。
转换后得到的单词必须是字典中的单词。

说明:

如果不存在这样的转换序列,返回一个空列表。
所有单词具有相同的长度。
所有单词只由小写字母组成。
字典中不存在重复的单词。
你可以假设 beginWord 和 endWord 是非空的,且二者不相同。

示例 1:

输入:
beginWord = “hit”,
endWord = “cog”,
wordList = [“hot”,“dot”,“dog”,“lot”,“log”,“cog”]

输出:
[
[“hit”,“hot”,“dot”,“dog”,“cog”],
[“hit”,“hot”,“lot”,“log”,“cog”]
]

示例 2:

输入:
beginWord = “hit”
endWord = “cog”
wordList = [“hot”,“dot”,“dog”,“lot”,“log”]

输出: []

解释: endWord “cog” 不在字典中,所以不存在符合要求的转换序列。

#include
#include
#include
#include
#include
#include
#include
using namespace std;


思路是:
bfs,难点在于如何保存路径,在于如何建图,思路在代码的注释中

class Solution {
public:
	//邻接表的图
	vector<vector<string>> G;
	unordered_set <string> set;
	vector<vector<string>> findLadders(string beginWord, string endWord, vector<string>& wordList) {
		//结果保存
		vector<vector<string>> res;
		//哈希表用O(1)的时间查找某个元素是否在表里
		for (string word : wordList)
		{
			set.insert(word);
		}
		//beginWord可能不在wordList,不在的话,就添加进去
		if (!set.count(beginWord))
		{
			wordList.insert(wordList.begin(), beginWord);
			set.insert(beginWord);
		}
		//邻接表表示图,初始化大小
		G.resize(wordList.size());
		//如果endword不在数组里面就结束了
		if (wordList.size() == 0 || !set.count(endWord)){
			return res;
		}
		//每个单词的长度
		int wordLen = beginWord.length();
		//用来判断是否被访问过
		unordered_map<string, bool> visited;
		//哈希表映射,用string,映射除在数组中的下标
		unordered_map<string, int> pos;
		for (int i = 0; i < wordList.size(); i++)
		{
			isConnected(i, wordList); /*建树*/
			visited[wordList[i]] = false;  //标注未访问
			pos[wordList[i]] = i;  //吧数组元素放入哈希表中
		}
		visited[beginWord] = true;
		//用bfs遍历图需要队列,队列中存储的是路径
		queue<vector<string>> q;
		//第一条路径
		vector<string>path;
		path.push_back(beginWord);
		q.push(path);
		int flag = 0;
		/*我们需要再每一层都遍历完,再把遍历过的结点标志为true,
		如果遍历一个结点就标志,可能这一层有几个结点,都与下一层同一个结点相连.如果标志了,那么就只添加了一条路径,
		必须在这一层遍历完之后,再把所有下一层的结点标志为true,下一层的结点保存在visit中*/
		vector<string> visit;
		while (!q.empty())
		{
			int current_size = q.size();
			if (flag) break;
			visit.clear();
			//一层一层遍历,循环结束就是遍历了一层并且吧下一层的结点添加到队列中
			for (int i = 0; i < current_size; i++)
			{
				//弹出一条路径
				vector<string> now = q.front(); q.pop();
				//获取路径上的最后一个结点
				string last = now.back();
				//通过映射获取下标
				int cur = pos[last];
				for (string& s : G[cur])
				{
					//如果下一层的结点是终点,添加到路径上,然后添加到结果中
					if (s == endWord){
						vector<string> tmp(now);
						tmp.push_back(s);
						res.push_back(tmp);
						flag = 1;
					}
					else if (!visited[s]){
						//如果没有被访问,就添加到路径中
						vector<string> tmp(now);
						tmp.push_back(s);
						visit.push_back(s);
						q.push(tmp);
					}
				}
			}
			//吧下一层的结点标志为访问
			for (int i = 0; i < visit.size(); i++)
			{
				visited[visit[i]] = true;
			}
		}
		return res;
	}
	void isConnected(int cur ,vector<string>& wordList)
	{
		//吧与下标为cur的相连的结点,添加到G[cur]的表中
		//判断是否相连的方法,就是修改word其中的一个字母然后判断是否在哈希表中
		int wordLen = wordList[0].length();
		for (int i = 0; i < wordLen; i++)
		{
			char origin = wordList[cur][i];
			for (char c = 'a'; c <= 'z'; c++)
			{ 
				if (c == origin) continue;
				wordList[cur][i] = c;
				if (set.count(wordList[cur])){
					G[cur].push_back(wordList[cur]);
				}
			}
			wordList[cur][i] = origin;
		}
	}
};

int main()
{
	string beginWord = "red";
	string endWord = "tax";
	vector<string> a;
	a.push_back("ted");
	a.push_back("tex");
	a.push_back("red");
	a.push_back("tax");
	a.push_back("tad");
	a.push_back("den");
	a.push_back("rex");
	a.push_back("pee");
	Solution s;
	s.findLadders(beginWord, endWord, a);
}

你可能感兴趣的:(力扣)