题目详情
给了A、B两个单词和一个单词集合Dict,每个的长度都相同。我们希望通过若干次操作把单词A变成单词B,每次操作可以改变单词中的一个字母,同时,新产生的单词必须是在给定的单词集合Dict中。求所有行得通步数最少的修改方法。
举个例子如下:
Given:
A = "hit"
B = "cog"
Dict = ["hot","dot","dog","lot","log"]
Return
[
["hit","hot","dot","dog","cog"],
["hit","hot","lot","log","cog"]
]
即把字符串A = "hit"转变成字符串B = "cog",有以下两种可能:
- "hit" -> "hot" -> "dot" -> "dog" -> "cog";
- "hit" -> "hot" -> "lot" -> "log" ->"cog"。
题目的基本思路是根据已有的单词构建一个图,然后从start开始用深度优先遍历所有的顶点,遍历到end记录遍历的路径。
代码如下:
#include <string>
#include <vector>
#include <iostream>
#include <set>
#include <map>
#include <algorithm>
using namespace std;
class Solution
{
public:
struct Node {
int num;
struct Node *next;
Node() {
next = NULL;
}
};
struct Graph {
Node **head; //链表头指针
map<string, int> string2int;
vector<string> int2string;
bool isStep(const string& a, const string& b) {
int cnt = 0;
for (int i=0; i<a.length(); i++) {
if (a[i] != b[i]) cnt ++;
if (cnt > 1) return false;
}
return true;
}
void insertEdge(int ii, int jj) {
Node *nd = new Node;
nd->num = jj;
nd->next = head[ii];
head[ii] = nd;
}
Graph(const set<string> &dict) {
head = new Node*[dict.size()];
for (int i=0; i<dict.size(); i++) head[i] = NULL;
int t = 0;
for (set<string>::const_iterator it=dict.begin(); it != dict.end(); it++) {
string2int[(*it)] = t++;
int2string.push_back(*it);
}
for (int i=0; i<int2string.size(); i++) {
for (int j=0; j<i; j++) {
if (isStep(int2string[i], int2string[j])) {
int ii = string2int[int2string[i]];
int jj = string2int[int2string[j]];
insertEdge(ii, jj);
insertEdge(jj, ii);
}
}
}
}
~Graph() {
for (int i=0; i<int2string.size(); i++) {
deleteHead(head[i]);
}
}
void deleteHead(Node *nd) {
if (nd != NULL) {
if (nd->next)
deleteHead(nd->next);
delete nd;
}
}
vector<vector<string>> ret;
void dfs(int starti, const int endi, vector<string> &path) {
visit[starti] = 1;
path.push_back(int2string[starti]);
if (starti == endi) {
ret.push_back(path);
path.pop_back();
visit[starti] = 0;
return;
}
for (Node *i=head[starti]; i!= NULL; i = i->next) {
if (!visit[i->num]) dfs(i->num, endi, path);
}
path.pop_back();
visit[starti] = 0;
}
vector<bool> visit;
void getAns(string& start, const string& end) {
int starti = string2int[start];
int endi = string2int[end];
visit.resize(int2string.size(), 0);
vector<string> path;
dfs(starti, endi, path);
}
};
public:
vector<vector<string>> findLadders(string start, string end, set<string>& dict)
{
dict.insert(start);
dict.insert(end);
Graph *g = new Graph(dict);
g->getAns(start, end);
vector<vector<string> > temp = g->ret;
int minStep = 0xfffffff;
for (int i=0; i<temp.size(); i++) {
if (temp[i].size() < minStep)
minStep = temp[i].size();
}
vector<vector<string> > ret;
for (int i=0; i<temp.size(); i++) {
if (temp[i].size() == minStep)
ret.push_back(temp[i]);
}
delete g;
return ret;
}
};
//start 提示:自动阅卷起始唯一标识,请勿删除或增加。
int main()
{
set<string> dict;
dict.insert("hot");
dict.insert("dot");
dict.insert("dog");
dict.insert("lot");
dict.insert("log");
string start = "hit";
string end = "cog";
Solution *s = new Solution;
vector<vector<string> > v = s->findLadders(start, end, dict);
delete s;
for (int i=0; i<v.size(); i++) {
for (int j=0; j<v[i].size(); j++) {
cout << v[i][j] << " ";
}
cout << endl;
}
return 0;
}
//end //提示:自动阅卷结束唯一标识,请勿删除或增加。
class Solution {
public:
void dfs(vector<vector<string> > &ret, map<string, int> &lay, string &cur, string &end, vector<string> &path, unordered_set<string> &dict) {
if(cur == end) {
ret.push_back(path);
return;
}
for(int i=0; i<cur.length(); i++) {
for(int j=0; j<26; j++) {
string t = cur;
if(t[i] != 'a' + j) {
t[i] = 'a' + j;
if(dict.find(t) != dict.end() && lay[cur] == lay[t]+1) {
path.push_back(t);
dfs(ret, lay, t, end, path, dict);
path.pop_back();
}
}
}
}
}
vector<vector<string> > findLadders(string start, string end, unordered_set<string> &dict) {
queue<string> q;
map<string, int> lay;
q.push(end);
lay[end] = 0;
while(!q.empty()) {
string s = q.front();
q.pop();
for(int i=0; i<s.length(); i++) {
string t = s;
for(int j=0; j<26; j++) {
if(t[i] != (char)('a' + j)) {
t[i] = (char)('a' + j);
if(dict.find(t) != dict.end() && lay.find(t) == lay.end()) {
lay[t] = lay[s] + 1;
q.push(t);
}
}
}
}
}
vector<vector<string> > ret;
vector<string> path;
path.push_back(start);
dfs(ret, lay, start, end, path, dict);
return ret;
}
};