http://oj.leetcode.com/problems/word-ladder/

图的最短路径问题,可以用最短路径算法,也可以深搜,也可以广搜。

深搜版本:

第一次写的时候,把sum和visited都自然的设置成了传引用,导致递归调用下去之后,再返回来,反而各种参数的值退不回来了。然后把sum和visited改成了传值,这样反而适应了本程序意图。可见,也不是什么时候都需要传引用的。具体在写程序的时候,需要传值还是传引用,要具体分析。传引用和传值的情况分别如下:

void DFS(string currentWord,string endWord,int &sum, unordered_set<string> &dict,map<string,bool>  &visited,int  &minDistance)
void DFS(string currentWord,string endWord,int &sum, unordered_set<string> &dict,map<string,bool>  &visited,int  &minDistance)
另外,还遇到了一个问题,在递归调用层次下去又上来后,对本层循环的,后续影响。所以又添加了两个变量,int tempSum;和map<string,bool> tempVisited;。给它们赋值成参数刚进来的样子,这样就摒除了同层循环间的相互影响。

深搜版本超时了,继续改……
#include <iostream>
#include <vector>
#include <string>
#include <unordered_set>
#include <map>
#include <hash_map>
#include <limits.h>
using namespace std; class Solution {
public: int calcDistance(string a,string b)
{
int sum = ;
for(int i = ;i<a.size();i++)
{
if(a[i]!=b[i])
sum++;
}
return sum;
} void DFS(string currentWord,string endWord,int sum, unordered_set<string> &dict,map<string,bool> visited,int &minDistance)
{
if(calcDistance(currentWord,endWord)==)
{
sum++;
if(minDistance> sum)
minDistance = sum;
return;
}
int tempSum;
map<string,bool> tempVisited;
for(unordered_set<string>::iterator iter = dict.begin();iter!=dict.end();iter++)
{
if(visited[*iter]==false && calcDistance(currentWord,*iter)==)
{
visited[*iter] = true;
tempSum = sum;
tempSum++;
tempVisited = visited;
DFS(*iter,endWord,tempSum,dict,visited,minDistance);
}
}
} int ladderLength(string start, string end, unordered_set<string> &dict) { string currentWord = start; int sum = ; map<string,bool> visited; for(unordered_set<string>::iterator iter = dict.begin();iter!=dict.end();iter++)
visited[*iter] = false; int minDistance = INT_MAX; DFS(currentWord,end,sum,dict,visited,minDistance); return minDistance;
}
}; int main()
{
Solution *mySolution = new Solution(); unordered_set<string> dict;
dict.insert("hot");
dict.insert("dot");
dict.insert("dog");
dict.insert("lot");
dict.insert("log");
string start = "hit";
string end = "cog"; cout<<mySolution->ladderLength(start,end,dict);
return ;
}

然后,写了一个广搜版本的,代码如下:

class Solution {

public:
class node{
public:
int distance;
string word;
bool visited;
public:
node()
{
distance = ;
word.clear();
visited = false;
}
}; int testDistance(string test,string end)
{
int distance = ;
for(int i = ;i<test.size();i++)
if(test[i]!= end[i])
distance++;
return distance;
} int ladderLength(string start, string end, unordered_set<string> &dict) { vector<node*> wordVector; unordered_set<string>::iterator itor=dict.begin(); for(int i = ;i<dict.size();i++)
{
node *myNode = new node();
myNode->word = *itor;
itor++;
wordVector.push_back(myNode);
} node *myNode = new node();
myNode->word = start; queue<node*> wordQueue;
wordQueue.push(myNode); node *topNode= new node(); while(!wordQueue.empty())
{
topNode = wordQueue.front();
wordQueue.pop();
if(testDistance(topNode->word,end) == )
{
return topNode->distance+;
}
else
{
node *pIndexNode = new node();
for(vector<node*>::iterator itor = wordVector.begin();itor!=wordVector.end();itor++)
{
pIndexNode = *itor;
if(pIndexNode->visited == false && testDistance(pIndexNode->word,topNode->word)==)
{
pIndexNode->visited = true;
pIndexNode->distance = topNode->distance+;
wordQueue.push(pIndexNode);
}
}
}
} }
};

在这个过程中,刚开始写的是

return topNode->distance++;就直接这样返回了,写程序过程中,细心不够,这样返回是distance本来的值,然后distance会++,但是那也没用了。

仍然没过。但是相比之下,广搜比深搜,在测试数据上有进步了。继续改进广搜版本,将testDistance函数改了,并且还是用了eraser函数,将已经加入过的元素删除了,代码如下:

#include <iostream>
#include <vector>
#include <string>
#include <unordered_set>
#include <queue>
using namespace std; class Solution {
public:
class node{
public:
int distance;
string word;
public:
node()
{
distance = ;
word.clear();
}
}; bool testDistance(string test,string end)
{
int distance = ;
for(int i = ;i<test.size();i++)
{
if(test[i]!= end[i])
distance++;
if(distance>=)
return false;
}
return true;
} int ladderLength(string start, string end, unordered_set<string> &dict) { vector<node*> wordVector; unordered_set<string>::iterator itor=dict.begin(); for(int i = ;i<dict.size();i++)
{
node *myNode = new node();
myNode->word = *itor;
itor++;
wordVector.push_back(myNode);
} node *myNode = new node();
myNode->word = start; queue<node*> wordQueue;
wordQueue.push(myNode); node *topNode= new node(); while(!wordQueue.empty())
{
topNode = wordQueue.front();
wordQueue.pop();
if(testDistance(topNode->word,end))
{
return topNode->distance+;
}
else
{
node *pIndexNode = new node();
for(vector<node*>::iterator itor = wordVector.begin();itor!=wordVector.end();)
{
pIndexNode = *itor;
if(testDistance(pIndexNode->word,topNode->word))
{
pIndexNode->distance = topNode->distance+;
wordQueue.push(pIndexNode);
itor = wordVector.erase(itor);
}
else
itor++;
}
}
} }
}; int main()
{
Solution *mySolution = new Solution(); unordered_set<string> dict;
dict.insert("hot");
dict.insert("dot");
dict.insert("dog");
dict.insert("lot");
dict.insert("log");
string start = "hit";
string end = "cog"; cout<<mySolution->ladderLength(start,end,dict);
return ;
}

虽然每一步都有学习到新东西,也学会了些深搜和广搜,但是这道题目仍然超时,现在考虑用空间换时间。

#include <iostream>
#include <vector>
#include <string>
#include <unordered_set>
#include <unordered_map>
#include <queue>
using namespace std; class Solution {
public:
bool testDistance(string test,string end)
{
int distance = ;
for(int i = ;i<test.size();i++)
{
if(test[i]!= end[i])
distance++;
if(distance>=)
return false;
}
return true;
} void BuildAdjacentList(string &word, unordered_map< string,unordered_set<string> >&adjacentList,const unordered_set<string> &dict)
{
string original = word;
for(size_t pos = ;pos<word.size();pos++)
{
char beforeChange = ' ';
for(int i = 'a';i<'z';++i)
{
beforeChange = word[pos];
if(beforeChange == i)
{
continue;
}
word[pos] = i;
if(dict.count(word)>)
{
auto iter = adjacentList.find(original);
if(iter!= adjacentList.end())
iter->second.insert(word);
else
{
adjacentList.insert(pair<string,unordered_set<string> >(original,unordered_set<string>()));
adjacentList[original].insert(word);
}
}
word[pos] = beforeChange;
}
}
} int ladderLength(string start, string end, unordered_set<string> &dict) { queue<pair<string,int> > wordQueue;
wordQueue.push(make_pair(start,)); unordered_map< string,unordered_set<string> > adjacentList; string topWord; int ans = ; unordered_set<string> visited;
visited.insert(start); while(!wordQueue.empty())
{
topWord = wordQueue.front().first; if(testDistance(topWord,end))
{
return wordQueue.front().second+;
}
else
{
BuildAdjacentList(topWord,adjacentList,dict); auto iter = adjacentList.find(topWord);
if(iter!= adjacentList.end())
{
for(unordered_set<string>::iterator iterset = iter->second.begin();iterset!= iter->second.end();iterset++)
{
if(visited.find(*iterset)==visited.end())
{
wordQueue.push(make_pair(*iterset,wordQueue.front().second+));
visited.insert(*iterset);
} }
} }
wordQueue.pop();
}
return ;
}
}; int main()
{
Solution *mySolution = new Solution(); unordered_set<string> dict;
dict.insert("hot");
//dict.insert("dot");
dict.insert("dog");
//dict.insert("lot");
//dict.insert("log");
string start = "hot";
string end = "dog"; cout<<mySolution->ladderLength(start,end,dict);
return ;
}

上面的这份代码,终于AC了,果然考察的重点在另一个思路上。其实,也用不着用空间来存储。比如可以使用更精简的代码,如下:

class Solution{
public:
int ladderLength(string start,string end,unordered_set<string> &dict)
{
queue<pair<string ,int > > wordQueue;
unordered_set<string> visited;
wordQueue.push(make_pair(start,));
visited.insert(start); while(!wordQueue.empty())
{
string curStr = wordQueue.front().first;
int curStep = wordQueue.front().second;
wordQueue.pop(); for(int i = ;i<curStr.size();i++)
{
string tmp = curStr;
for(int j = ;j<;++j)
{
tmp[i] = j+'a';
if(tmp == end)
return curStep+;
if(visited.find(tmp) == visited.end() && dict.find(tmp)!=dict.end())
{
wordQueue.push(make_pair(tmp,curStep+));
visited.insert(tmp);
}
}
}
}
return ; }
};

加油!

 其实,这道题的重点不在于深搜、广搜剪枝之类的。换个角度说的话,dict很大,多次遍历它的话,影响时间,然后换个思路……

LeetCode OJ——Word Ladder的更多相关文章

  1. Java for LeetCode 126 Word Ladder II 【HARD】

    Given two words (start and end), and a dictionary, find all shortest transformation sequence(s) from ...

  2. [LeetCode] 126. Word Ladder II 词语阶梯 II

    Given two words (beginWord and endWord), and a dictionary's word list, find all shortest transformat ...

  3. [LeetCode] 127. Word Ladder 单词阶梯

    Given two words (beginWord and endWord), and a dictionary's word list, find the length of shortest t ...

  4. LeetCode 126. Word Ladder II 单词接龙 II(C++/Java)

    题目: Given two words (beginWord and endWord), and a dictionary's word list, find all shortest transfo ...

  5. [Leetcode Week5]Word Ladder II

    Word Ladder II 题解 原创文章,拒绝转载 题目来源:https://leetcode.com/problems/word-ladder-ii/description/ Descripti ...

  6. [Leetcode Week5]Word Ladder

    Word Ladder题解 原创文章,拒绝转载 题目来源:https://leetcode.com/problems/word-ladder/description/ Description Give ...

  7. [LeetCode] 126. Word Ladder II 词语阶梯之二

    Given two words (beginWord and endWord), and a dictionary's word list, find all shortest transformat ...

  8. 【leetcode】Word Ladder

    Word Ladder Total Accepted: 24823 Total Submissions: 135014My Submissions Given two words (start and ...

  9. 【leetcode】Word Ladder II

      Word Ladder II Given two words (start and end), and a dictionary, find all shortest transformation ...

随机推荐

  1. http 基础与通讯原理

    目录 http 基础与通讯原理 Internet 与中国 1990年10月 注册CN顶级域名 1993年3月2日 接入第一根专线 1994年4月20日 实现与互联网的全功能连接 1994年5月21日 ...

  2. 2.什么是composer与packgist,composer的安装

    目录 学习地址: composer与packgist关系图片 composer的安装; 配置composer 修改国内镜像 用composer安装与卸载插件 composer插件升级后报错 学习地址: ...

  3. Python基础-包与模块

    Python基础-包与模块 写在前面 如非特别说明,下文均基于Python3 摘要 为重用以及更好的维护代码,Python使用了模块与包:一个Python文件就是一个模块,包是组织模块的特殊目录(包含 ...

  4. Python学习笔记:面向对象(类)

    1.类定义:Python3中,如果新建的类没有继承任何其他类,默认继承基础类object.Python2中如果没有显式继承object类就是经典类,而显式继承了object类就是新式类,Python2 ...

  5. LeetCode(123) Best Time to Buy and Sell Stock III

    题目 Say you have an array for which the ith element is the price of a given stock on day i. Design an ...

  6. NSNotificationCenter的用法

    作用:NSNotificationCenter是专门供程序中不同类间的消息通信而设置的. 注册通知:即要在什么地方接受消息 [[NSNotificationCenter defaultCenter]  ...

  7. 浅谈CSS中的百分比

    结论: 标准流中的元素,看其属性有没有继承性.对于width和margin-left,它是可以继承的,它会参照父元素或者祖先元素(其实是包含块):对于height,它没有继承性,父元素或者祖先元素会自 ...

  8. luogu3376 【模板】网络最大流 dinic

    当前弧优化 #include <iostream> #include <cstring> #include <cstdio> #include <queue& ...

  9. 实现类似QQ单一账户登录,在另一个地方登录后在原登录窗口提示下线

    首先,使用框架做的最好,可以在框架页直接做一次就好了 再登陆成功后保存session的代码后添加以下代码: 注意:需要引入命名空间using System.Collections; SetApplic ...

  10. webdriver高级应用- 操作富文本框

    富文本框的技术实现和普通的文本框的定位存在较大的区别,富文本框的常见技术用到了Frame标签,并且在Frame里面实现了一个完整的HTML网页结构,所以使用普通的定位模式将无法直接定位到富文本框对象. ...