LeetCode第126题单词接龙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” 不在字典中,所以不存在符合要求的转换序列。

写这题如果对图不太了解的话,将很难做下去,说实话LZ写这题花了很久,又不希望去百度别人的答案或者方法,所以就绞尽脑汁想方法。

所以希望看到这篇博客的人尽量不要去研究代码了。。。我会尽量把思路叙述清楚。
(1)拿到一个beginword,你需要检查从beginWord能不能(经过一次)变成Wordlist【】里面的单词,如果可以,继续下去,否则直接返回
(2)拿到一个endWord,你需要检查wordlist【】里面是否有这个单词,如果有,继续下去,否则直接返回。
(3)通过(1)(2)后,我们就肯定能找到一个进入Wordlist【】的入口first_step 【】(ps::beginWord经过一个char变化的单词(or单词组)),把这些入口,其实就是Wordlist的下标存储起来,至于进入到Wordlist【】之后该怎么办,继续往后走。
(4)接着你还要继续做前导工作,我们需要知道,Wordlist【】内部,每个单词可以转化为的下一个单词是什么!!!(只需要存他的下标就行了),以及我们要知道当前单词,到最终的endword需要转化的最小次数!!!后面可以转化的单词为next_hop【】,当前单词到endword的最小次数为min_distance,把他们封装到一个结构体里Hash_nodes(改造的图)

struct Hash_nodes{
	vector<int>next_hop;
	int min_distance_to_endPosition;
};

vector<Hash_nodes>hash_wordlist(wordList.size()); 例如 :hash_wordlist【i】.next_hop【】存的是Wordlist【i】单词的所有的后继可转化单词的下标
hash_wordlist【i】.min_distance_to_endPosition表示当前单词到Wordlist的最小转化数
(5)接下来到了最重要的一步,求每个单词到endword的最小步数(或者是说最小转化数),这个将决定,你的时间复杂度的高低!!!对于Wordlist【】内部的单词,他们的下一跳单词,我们当然很容易就求出来了,但是!!!我们只能要那些下一跳单词到endword最近的单词!!!即我们要保证,我们当前要转化为的单词是最好的,最短的,不做无用功(贪心算法的思想!!)
求每个单词的最小转化数(min_distance_to_endPosition):我们要从endword所在位置(endword_position)开始,因为这个点的所在的min_distance=0;而且他的所有的下一个可转化单词(逆向看的话正好一步可以变成endword的单词)所在位置的min_distance一定是1,再往回推,下一个单词的下一个单词的min_distance一定是2
是不是感觉可以用递归来初始化????注意!!!!不要用递归来写这个,因为这个是无向图,很容易造成环路,建议用循环写,用队列或者双vector<>,队列为空的时候就初始化完了。
(6)拿到这个初始化过后的vector<Hash_nodes>hash_wordlist(wordList.size())
我们还要进行删改因为每个单词的后继单词有很多,我们只想要后继单词的min_distance最小(其他的全部删除掉,当然不删除也可以,只不过后续的操作会稍微麻烦一点)
(7)完成了上述的各种前导工作后,可以进行最终的寻找单词接龙过程;
beginWord的接口在(3)中已经求过为first_step 【】,依次选first_step 【i】为入口单词,在hash_wordlist【】内部往后走,最终只要走到endword_position位置了,这个path一定是最短的。

代码如下(一些打印函数是我自己封装的类,已经被我屏蔽掉了,为了方便理解,主调函数内部有一些操作说明,而且我们对Wordlist【】的操作基本上全是对下标的操作!!!最终才转化为string):

struct Hash_nodes{
	vector<int>next_hop;
	int min_distance_to_endPosition;
};
class Solution {
public:
bool check_one_different(string &a, string &b){
		int compare = 0;
		for (int i = 0; i <= a.size() - 1; i++){
			if (compare >= 2)break;
			if (a[i] != b[i])compare++;
		}
		if (compare == 1) return true;
		else return false;
	}
	int find_string_from_vector(string &s, vector<string>& wordList){
		for (int i = 0; i <= wordList.size() - 1; i++){
			int j;
			for (j = 0; j <= wordList[i].size() - 1; j++){
				if (s[j] != wordList[i][j]) break;
			}
			if (j >= wordList[i].size()) return  i;
		}
		return -1;
	}

	void chushi_hash_wordlist_minDistance(vector<Hash_nodes>&hash_wordlist, int &end_position){
		vector<int>m; 
		m.push_back(end_position);
		while (m.size() != 0){
			vector<int>next_m;
			for (int i = 0; i <= m.size() - 1; i++){
				int now_position = m[i];
				if (hash_wordlist[now_position].next_hop.size() > 0){
					for (int j = 0; j <= hash_wordlist[now_position].next_hop.size() - 1; j++){
						int nextHop = hash_wordlist[now_position].next_hop[j];
						if (hash_wordlist[now_position].min_distance_to_endPosition + 1 < hash_wordlist[nextHop].min_distance_to_endPosition){
							hash_wordlist[nextHop].min_distance_to_endPosition = hash_wordlist[now_position].min_distance_to_endPosition + 1;
							next_m.push_back(nextHop);
						}
					}
				}
			}
			m = next_m;
		}
	}
	void chushi_hash_wordlist_nextHop(vector<Hash_nodes>&hash_wordlist, int endword_position, vector<string>& wordList){
		for (int i = 0; i <= wordList.size() - 1; i++){
			//cout << "i==" << i << endl;
			for (int j = 0; j <= wordList.size() - 1; j++){
				if (i == j)continue;
				bool tmp = check_one_different(wordList[j], wordList[i]);
				if (tmp)  hash_wordlist[i].next_hop.push_back(j); //{cout << "j==";  cout << j << "   "; }
			}
			//cout << endl;
		}
		for (int i = 0; i <= hash_wordlist.size() - 1; i++)
			hash_wordlist[i].min_distance_to_endPosition = INT_MAX;
		hash_wordlist[endword_position].min_distance_to_endPosition = 0;
	}
	vector<int> get_first_step(string beginWord, vector<string>& wordList, vector<Hash_nodes>hash_wordlist){
		vector<int>m;
		for (int i = 0; i <= wordList.size() - 1; i++){
			if (check_one_different(beginWord, wordList[i])) m.push_back(i);
		}
		int min_distance = INT_MAX;
		if (m.size() > 0){
			for (int i = 0; i <= m.size() - 1; i++){
				int position = m[i];
				min_distance = min(min_distance, hash_wordlist[position].min_distance_to_endPosition);
			}
			vector<int>::iterator p = m.begin();
			while (p != m.end()){
				int position = (*p);
				if (hash_wordlist[position].min_distance_to_endPosition > min_distance) p = m.erase(p);
				else p++;
			}
		}
		return m;
	}
	void erase_hash_wordlist_nextHop(vector<Hash_nodes>&hash_wordlist){
		for (int i = 0; i <= hash_wordlist.size() - 1; i++){
			if (hash_wordlist[i].min_distance_to_endPosition == 0)continue;
			int min_step = INT_MAX; 
			//下面对hash_wordlist[i].next_hop[]这个数组操作
			vector<int>::iterator p = hash_wordlist[i].next_hop.begin();
			while (p != hash_wordlist[i].next_hop.end()){
				int next_position = (*p);
				if (hash_wordlist[next_position].min_distance_to_endPosition < min_step)
				 min_step = hash_wordlist[next_position].min_distance_to_endPosition; 
				p++;
			}
			for (p = hash_wordlist[i].next_hop.begin(); p != hash_wordlist[i].next_hop.end();){
				int next_position = (*p);
				if (hash_wordlist[next_position].min_distance_to_endPosition > min_step)
					p = hash_wordlist[i].next_hop.erase(p);
				else p++;
			}
		}
	}
	bool digui(int begin_position, int end_position, vector<Hash_nodes>&hash_wordlist,vector<vector<int>>&total,vector<int>&dange){
		vector<int>next_hop = hash_wordlist[begin_position].next_hop;
		//if (hash_wordlist[begin_position].min_distance_to_endPosition == 1)return true;
		if (begin_position==end_position)return true;
		for (int i = 0; i <= next_hop.size() - 1; i++){
		   dange.push_back(next_hop[i]);
		   bool tmp=digui(next_hop[i], end_position,hash_wordlist,total,dange);
		   if (tmp)total.push_back(dange);
		   vector<int>::iterator p = dange.end() - 1; p = dange.erase(p);
		}
		return false;
	}
	void from_position_to_string(string beginWord, string endWord, vector<string>& wordList, vector<vector<string>>&m, vector<vector<int>>&total){
		for (int i = 0; i <= total.size() - 1; i++){
			vector<string>tmp; tmp.push_back(beginWord);
			for (int j = 0; j <= total[i].size() - 1; j++){
				int position = total[i][j]; tmp.push_back(wordList[position]);
			}
			//tmp.push_back(endWord);
			m.push_back(tmp);
		}
	}
	vector<vector<string>> findLadders(string beginWord, string endWord, vector<string>& wordList) {
		vector<vector<string>>m;
		vector<Hash_nodes>hash_wordlist(wordList.size());
		int endword_position = find_string_from_vector(endWord, wordList);
		if (endword_position == -1)return m;
		chushi_hash_wordlist_nextHop(hash_wordlist,endword_position, wordList);
		chushi_hash_wordlist_minDistance(hash_wordlist, endword_position);
		//上面会得到 所有单词到达 endword的情况
		//下面我们要筛选nextHop 因为 他的所有下一跳 我们只要最短的!!!!!!!!
		//保证我们的下一跳是最优结果
		//print_hash(hash_wordlist);
		erase_hash_wordlist_nextHop(hash_wordlist);
		//cout << "++++++++++++++++++++++++++++++++++++++++++++++" << endl;
		//print_hash(hash_wordlist);
		vector<int>first_step = get_first_step(beginWord, wordList, hash_wordlist);
		//print.print_onearry(first_step);
		if (first_step.size() == 0) return m;
		vector<vector<int>>total;
		for (int i = 0; i <= first_step.size() - 1; i++){
			vector<int>dange; 
			if (first_step[i] == endword_position) { dange.push_back(endword_position); total.push_back(dange); }
			else{
				dange.push_back(first_step[i]);
				digui(first_step[i], endword_position, hash_wordlist, total, dange);
			}
		}
		if(total.size()>0) from_position_to_string(beginWord, endWord, wordList, m, total);
		//print.print_twoarry(m);
		return m;
	}

};```

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值