还是太菜了,第一次做到图的题目,一开始习惯性的想到DFS,后来发现跑出来超时,超时的点在:
1.DFS是一个个的把与之相邻的某个i节点遍历完后在遍历另一个相邻的j节点,而BFS是按层次遍历的,即先遍历完与之相邻的一层,然后再遍历相邻一层的下一层,这样BFS只要找到某个节点符合要求,就一定是最短的(因为是按层次遍历的)。
2.每次转换只能改变一个字母,这个地方没什么思路,只想到了每次改变都要遍历字典一个个位置对比或者按字母表更改后查找。。。。。
给定两个单词(beginWord 和 endWord)和一个字典,找到从 beginWord 到 endWord 的最短转换序列的长度。转换需遵循如下规则:
每次转换只能改变一个字母。
转换过程中的中间单词必须是字典中的单词。
说明:
如果不存在这样的转换序列,返回 0。
所有单词具有相同的长度。
所有单词只由小写字母组成。
字典中不存在重复的单词。
你可以假设 beginWord 和 endWord 是非空的,且二者不相同。
思路:
1.将beginWord加入字典后,对字典内的所有节点构筑图。
2.BFS遍历图,直到出现满足endWord要求的节点。另外为了避免环,要准备一个set来记录队列中的节点,不然如果有环会出现循环无法结束。
graph为图,图只是一种数据结构,不一定要按书上的邻接表的那种形式,实际上这里用map<string,vector<string>>的形式也建立了图。
图的建立:
遍历词典,每遍历一个节点,建立这两个点间的通道。所以第二层for从j+1开始即可。比如A B C D中,遍历A时已经建立了A到C和C到A的通道,因此遍历到C时就不用从A开始,直接从D开始即可。
建立完图后用BFS进行遍历:
每次pop后在队列中加入与pop的节点相邻的节点,注意加入的节点要求未在set中出现过,不然会产生换,加入后也要马上在set中插入。
其他的就没什么好说的了,整体思路想清楚还是挺简单的,做完这个题收货还是很大的,虽然复杂度还是很高。
还是自己太菜了太菜了太菜了我好菜呀!!!!
class Solution { public: int ladderLength(string beginWord, string endWord, vector<string>& wordList) { wordList.push_back(beginWord); map<string,vector<string>> graph; set<string> table; queue<pair<string,int>> qu; construct(wordList,graph); qu.push(make_pair(beginWord,1)); table.insert(beginWord); while(!qu.empty()) { pair<string,int> node=qu.front(); if(node.first==endWord) { return node.second; } qu.pop(); for(int i=0;i<graph[node.first].size();i++) { auto tmp=graph[node.first][i]; if(table.find(tmp)==table.end()) { qu.push(make_pair(tmp,node.second+1)); table.insert(tmp); } } } return 0; } bool comstring(string& a,string& b) { int cnt=0; for(int i=0;i<a.size();i++) { if(a[i]!=b[i]) cnt++; } return cnt==1; } void construct(vector<string>& wordList,map<string,vector<string>>& graph) { for(int i=0;i<wordList.size();i++) graph[wordList[i]]=vector<string>(); for(int i=0;i<wordList.size();i++) { for(int j=i+1;j<wordList.size();j++) { if(comstring(wordList[i],wordList[j])) { graph[wordList[i]].push_back(wordList[j]); graph[wordList[j]].push_back(wordList[i]); } } } } };