标签:节点 单词 vector 接龙 beginWord ans endWord path LeetCode
给定一个起始字符串和一个终止字符串,以及一个单词表,求是否可以将起始字符串酶促改一个字符,
直到改成终止字符串,且所有中间的修改过程表示的字符串都可以在单词表里面找到.若存在,输出
需要修改次数最少的所有更改方式.
示例 1
Input:beginWord="hit",endWord="cog",wordList=["hot","dot","lot","log","cog"]
Output:[["hit","hot","dog","cog"],
["hit","hot",log","cog"]]
解题思路:
我们可以把起始字符串,终止字符串,以及单词表里面所有的字符串想象成节点.若两个字符串只有一个字符不同,
那么它们相连.因为题目需要输出修改次数最少的所有修改方式,因此可以使用广度优先搜索,求得起始节点到
终止节点的最短距离.
同时还使用一个小技巧:并不是直接从起始节点进行广度优先搜索,直到找到终止节点为止:而是从起始节点和
终止节点分别进行广度优先搜索,每次只延展当前层节点数最少的那一端,这样可以减少搜索的总结点数.举例来说,
假设最短距离为4,如果只从一端搜索4层,总遍历节点数最多是1+2+4+8+16=31;而如果从两端各搜索两层,总
遍历节点数最多只有2x(1+2+4)=14;
在搜索结束后,还需要通过回溯法来重建所有可能的路径.
#include <iostream>
#include <vector>
#include <unordered_set>
#include <unordered_map>
#include <algorithm>
using namespace std;
class Solution{
public:
vector<vector<string>> findLadders(string beginWord,string endWord,vector<string>& wordList){
vector<vector<string>> ans;
unordered_set<string> dict;
for(const auto&w:wordList)
dict.insert(w);
if(!dict.count(endWord))/*set容器查找,返回0或者1*/
return ans;
dict.erase(beginWord);
dict.erase(endWord);
unordered_set<string> q1{beginWord},q2{endWord};
unordered_map<string,vector<string>> next;
bool reversed=false,found=false;
/*广度优先遍历*/
while(!q1.empty()){
unordered_set<string> q;
for(const auto&w:q1){
string s=w;
for(size_t i=0;i<s.size();i++){
char ch=s[i];
for(size_t j=0;j<26;j++){
s[i]=j+'a';
if(q2.count(s)){
reversed?next[s].push_back(w):next[w].push_back(s);
found=true;
}
if(dict.count(s)){
reversed?next[s].push_back(w):next[w].push_back(s);
cout<<s<<endl;
q.insert(s);
}
}
s[i]=ch;
}
}
if(found){
break;
}
for(const auto& w:q){
dict.erase(w);
}
if(q.size()<=q2.size()){
q1=q;
}else{
reversed=!reversed;
q1=q2;
q2=q;
}
}
/*回溯符合条件的路径*/
if(found){
vector<string> path={beginWord};
backtrack(beginWord,endWord,next,path,ans);
}
return ans;
}
private:
void backtrack(const string& src,const string& dst,unordered_map<string,
vector<string>>&next,vector<string>&path,vector<vector<string>>& ans){
if(src==dst){
ans.push_back(path);
return;
}
for(const auto&s:next[src]){
path.push_back(s);
backtrack(s,dst,next,path,ans);
path.pop_back();
}
}
};
int main(int argc,char* argv[]){
string beginWord="hit",endWord="cog";
vector<string> wordList={"hot","dot","lot","log","cog"};
vector<vector<string>> ans=Solution().findLadders(beginWord,endWord,wordList);
for_each(ans.begin(),ans.end(),[](vector<string>& res){
cout<<"[ ";
for(const auto&i:res)
cout<<i<<" ";
cout<<"]";
});
return 0;
}
标签:节点,单词,vector,接龙,beginWord,ans,endWord,path,LeetCode
来源: https://blog.csdn.net/Jiangtagong/article/details/110809002
本站声明:
1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。