15-05-10 更新,按照最下面的解法进行优化,得到AC代码,并且比他快。值得一开心。
class WordNode {
public:
string value;
unordered_set<WordNode*> Parents;
WordNode(string v) :value(v) { }
};
vector<vector<string>> gres;
vector<string> gtmp;
void checkOneNode(string end, WordNode* node) {
gtmp.push_back(node->value);
if (node->value == end) {
vector<string> tmp_res = gtmp;
gres.push_back(tmp_res);
gtmp.pop_back();
return;
}
for (auto it : node->Parents) {
checkOneNode(end, it);
}
gtmp.pop_back();
}
vector<vector<string>> findLadders(
string start, string end,
unordered_set<string> &dict) {
dict.insert(start);
WordNode* start_node = NULL;
WordNode* end_node = new WordNode(end);
unordered_map<string, WordNode*> curr_flow, next_flow;
curr_flow[end] = end_node;
string current_word = "";
int n = end.length(), ch;
string a;
//construct a reverse tree
//first create end node, then find words can transform to end,
//and create edge(word, end), do it recursively until find start.
bool done = false;//if find the start, stop
while (!done && !curr_flow.empty()) {
for (auto it : curr_flow) {
current_word = it.first;
for (int j = 0; j < n; j++) {
ch = current_word[j] - 'a';
for (int k = 0; k < 26; k++) {
if (k == ch) continue;
current_word[j] = 'a' + k;
if (dict.find(current_word) != dict.end()) {
//first time add a word to the tree, create it's node
if (next_flow[current_word] == NULL) {
next_flow[current_word] = new WordNode(current_word);
if (current_word == start) {
done = true;
start_node = next_flow[current_word];
}
}
//create edge(new_word, current_layer_word)
next_flow[current_word]->Parents.insert(it.second);
}
}//end of 26 letters
current_word[j] = 'a' + ch;
}//end of word's length
}//end of curr_flow
curr_flow = next_flow;
next_flow.clear();
for (auto it : curr_flow) dict.erase(it.first);
}
if (!done) {
return vector<vector<string>>();
}
//deep first search for ladders
checkOneNode(end, start_node);
return gres;
}
做了三天。从一开始的只会用遍历,到后来优化遍历条件,再到尝试用图和BFS做,真是脑子不够了。
还是不够AC,太慢了。
struct MapNode{
public:
bool added;
string val;
list<MapNode *> neighbors;
vector<list<MapNode *>> routes;
MapNode(string s) :added(false), val(s){}
void RemoveNeighbor(string s);
};
vector<vector<string>> findLadders(string start, string end, unordered_set<string> &dict) {
vector<vector<string>> res;
string a;
int n = start.length();
int i = 0, difcount = 0;
while (i < n){
if (start[i] != end[i++])difcount++;
if (difcount>1)break;
}
if (difcount == 1)
{
vector<string> tmp;
tmp.push_back(start), tmp.push_back(end);
res.push_back(tmp);
return res;
}
MapNode *sp = new MapNode(start);
MapNode *ep = new MapNode(end);
list<MapNode *> nodelist;
nodelist.push_back(sp), nodelist.push_back(ep);
//build map
for (auto it : dict){
MapNode *tmp = new MapNode(it);
for (auto qit : nodelist){
i = 0, difcount = 0;
a = qit->val;
while (i < n){
if (a[i] != it[i++])difcount++;
if (difcount > 1)break;
}
if (difcount == 1)
{
qit->neighbors.push_back(tmp);
tmp->neighbors.push_back(qit);
}
}
nodelist.push_back(tmp);
}
/**/
//bsf
queue<MapNode *> q;
sp->added = true;
list<MapNode *> st;
st.push_back(sp);
sp->routes.push_back(st);
q.push(sp);
int count = 1;
while (q.size()>0){
MapNode *qtmp = q.front();
q.pop();
if (count == 0){
count = q.size();
}
count--;
for (auto qit = qtmp->neighbors.begin(); qit != qtmp->neighbors.end(); qit++){
MapNode *tmp = *qit;
tmp->neighbors.remove(qtmp);
if (tmp->routes.size() == 0)
{
for (auto rit : qtmp->routes){
rit.push_back(tmp);
tmp->routes.push_back(rit);
}
}
else{
list<MapNode *> prelist = qtmp->routes.front();
list<MapNode *> nextlist = tmp->routes.front();
if (prelist.size() + 1 > nextlist.size())continue;
if (prelist.size() + 1 < nextlist.size())tmp->routes.clear();
for (auto rit : qtmp->routes){
rit.push_back(tmp);
tmp->routes.push_back(rit);
}
}
if (!tmp->added){
tmp->added = true;
q.push(tmp);
}
}
if (count == 0 && ep->routes.size()>0)
{
break;
}
}
for (auto rit : ep->routes)
{
vector<string> tmp;
for (auto mnode : rit){
tmp.push_back(mnode->val);
}
res.push_back(tmp);
}
return res;
}
2015-05-10更新一个思路,比之前好一些,不过还是不够AC。
bool isAlike(string a, string b) {
int c = 0, n = a.length();
for (size_t i = 0; i < n; i++) {
if (a[i] != b[i]) c++;
if (c > 1) return false;
}
return c == 1;
}
class WordNode {
public:
string value;
unordered_set<WordNode*> Parents;
WordNode(string v) :value(v) { }
};
vector<vector<string>> gres;
vector<string> gtmp;
void checkOneNode(string end, WordNode* node) {
gtmp.push_back(node->value);
if (node->value == end) {
vector<string> tmp_res = gtmp;
gres.push_back(tmp_res);
gtmp.pop_back();
return;
}
for (auto it : node->Parents) {
checkOneNode(end, it);
}
gtmp.pop_back();
}
vector<vector<string>> findLadders(
string start, string end,
unordered_set<string> &dict) {
vector<vector<string>> path;
vector<string> res;
vector<vector<string>> ress;
if (isAlike(start, end)) {
res.push_back(start);
res.push_back(end);
ress.push_back(res);
return ress;
}
swap(start, end);//trying to build a reverse tree
unordered_set<WordNode*> vec_dict;
int index = 0;
for (auto dit : dict) {
WordNode* curr_node = new WordNode(dit);
vec_dict.insert(curr_node);
}
WordNode* end_node = new WordNode(end);
vec_dict.insert(end_node);
return ress;
WordNode* root = new WordNode(start);
WordNode* wn_pointer = root;
unordered_set<WordNode*> flow[2];
int curr_flow = 0, other_flow = 1;
flow[curr_flow].insert(root);
string current_word = "";
int i, difcount, n = end.length();
string a;
//construct the tree
bool done = false, empty = false;//if find the end, stop
while (!done && !empty) {
for (auto it : flow[curr_flow]) {
current_word = it->value;
empty = true;
//find current_word's transformable words in dict
for (auto dit : vec_dict) {
i = 0;
a = dit->value;
while (i < n){
if (a[i] != current_word[i++]) {
a[i - 1] = current_word[i - 1];
break;
}
}
if (a == current_word) {
empty = false;
dit->Parents.insert(it);
flow[other_flow].insert(dit);
if (dit->value == end) {
done = true;//if reach the end
}
}
}//end of find current_word's transformable words
}//end of curr_flow
flow[curr_flow] = unordered_set<WordNode*>();
curr_flow = other_flow;
other_flow = 1 - curr_flow;
for (auto it : flow[curr_flow]) vec_dict.erase(it);
if (empty && !flow[curr_flow].empty()) empty = false;
}
if (!done) {
return ress;
}
//deep first search for ladders
checkOneNode(start, end_node);
return gres;
}
看看别人怎么做的吧。
经过几天的不断学习(0 0),终于AC了。。 还是改进别人的代码做的。
class Solution {
public:
unordered_multimap<string, string> lmap;
vector<vector<string>> res;
void getPath(string curr, string end, vector<string> path){
if (curr == end)
{
path.push_back(end);
res.push_back(path);
return;
}
path.push_back(curr);
unordered_multimap<string, string>::iterator it;
pair<unordered_multimap<string, string>::iterator, unordered_multimap<string, string>::iterator > range = lmap.equal_range(curr);
for (it = range.first; it != range.second; it++)
{
getPath(it->second, end, path);
}
path.pop_back();
}
vector<vector<string>> findLadders(string start, string end, unordered_set<string> &dict) {
string a;
int n = start.length();
//1. push end, find all next level words and push the pairs into lmap;
//2. find all next level words and push the pairs into lmap until start in lmap;
//3. find path and save in res
unordered_set<string> last_layer, curr_layer;
//unordered_set<string> levels[2]; //takes about double time
//int currl = 0, prevl = 1;
int itmp, i, j;
string stmp;
curr_layer.insert(end);
dict.insert(start);
bool flag = false;
while (curr_layer.size() > 0 || last_layer.size() > 0)
{
for (unordered_set<string>::iterator it = last_layer.begin(); it != last_layer.end(); it++)
{
dict.erase(*it);
}
last_layer.clear();
for (unordered_set<string>::iterator it = curr_layer.begin(); it != curr_layer.end(); it++)
{
for (i = 0; i < n; i++)
{
stmp = *it;
itmp = stmp[i] - 'a';
for (j = 1; j < 26; j++)
{
stmp[i] = (itmp + j) % 26 + 'a';
if (dict.find(stmp) != dict.end())
{
lmap.insert(make_pair(stmp, *it));
last_layer.insert(stmp);
}
}
}
}
curr_layer = last_layer;
if (curr_layer.count(start) > 0)
{
break;
}
}
vector<string> path;
if (lmap.size() > 0)getPath(start, end, path);
return res;
}
};