120-单词接龙

给出两个单词(start和end)和一个字典,找到从start到end的最短转换序列

比如:

每次只能改变一个字母。

变换过程中的中间单词必须在字典中出现。

注意事项

  • 如果没有转换序列则返回0。
  • 所有单词具有相同的长度。
  • 所有单词都只包含小写字母。

样例

给出数据如下:

start = "hit"

end = "cog"

dict = ["hot","dot","dog","lot","log"]

一个最短的变换序列是 "hit" -> "hot" -> "dot" -> "dog" -> "cog",

返回它的长度 5

标签

领英 宽度优先搜索

思路

可以将此题理解为求图中两点的最短路径,dict 中每个单词是一个节点,start 与 end 也是图中的节点,若两个单词中只有一个字母不同(如 "hit" "hot" "dog")在,则这两个节点是联通的。故问题就转化成了在图中求节点 start 到节点 end 的最短路径。

因为只需要知道路径长度而非具体路径,所以可以简单使用宽度优先搜索,从 start 开始搜索 end,每扩大一层,路径长度 +1

方法一(最开始想到的,但提交超时)

使用队列 path 记录搜索顺序,pathCount 记录每个节点与 start 节点的距离(即路径长度),每次将与对列的头节点相连且未遍历的节点加入到队列并标记其已经遍历,更新此节点距离

code

class Solution {
public:
/**
* @param start, a string
* @param end, a string
* @param dict, a set of string
* @return an integer
*/
int ladderLength(string start, string end, unordered_set<string> &dict) {
// write your code here
int size = dict.size();
if (size <= 0) {
return 0;
} dict.insert(end);
map<string, bool> isVisited;
map<string, int> pathCount;
queue<string> path; path.push(start);
isVisited[start] = true;
pathCount[start] = 1;
pathCount[end] = 0; while (!path.empty()) {
string last = path.front();
path.pop();
for (string str : dict) {
if (isVisited[str] == false && isConnect(str, last)) {
path.push(str);
isVisited[str] = true;
pathCount[str] = pathCount[last] + 1;
if (str == end) {
return pathCount[end];
}
}
}
}
return pathCount[end];
} bool isConnect(string str1, string str2) {
int distance = 0;
for (int i = 0; i < str1.size(); i++) {
if (str1[i] != str2[i]) {
distance++;
if (distance > 1) {
return false;
}
}
}
if (distance == 1) {
return true;
}
else {
return false;
}
}
};

方法二(AC)

网上普遍的解法,在遍历节点的相邻节点处做了优化,在得到队列头结点时,枚举所有与头结点相连的节点值,并判断此值是否在图中(即 dict 中)。若此节点未被遍历过(即此节点存在于 dict),将其加入队列并更新距离,然后将此节点删除(减少搜索代价),否则,继续枚举

code

class Solution {
public:
/**
* @param start, a string
* @param end, a string
* @param dict, a set of string
* @return an integer
*/
int ladderLength(string start, string end, unordered_set<string> &dict) {
// write your code here
int size = dict.size();
if (size <= 0) {
return 0;
}
if(start.size() == end.size() && start.size() == 1) {
return 1;
} map<string, int> pathCount;
queue<string> path; path.push(start);
pathCount[start] = 1; dict.erase(start);
dict.insert(end); while (dict.size() > 0 && !path.empty()) {
string last = path.front();
path.pop();
for (int i = 0; i < last.size(); i++) { // 枚举可能相连的节点值
string str = last;
for (char j = 'a'; j <= 'z'; j++) { // 枚举可能相连的节点值
if (str[i] == j) {
continue;
}
else {
str[i] = j;
}
if (dict.find(str) != dict.end()) { // 枚举的值在图中存在且未被遍历
path.push(str);
pathCount[str] = pathCount[last] + 1;
dict.erase(str);
}
if (str == end) { // 找到
return pathCount[end];
}
}
}
} return 0;
}
};

lintcode-120-单词接龙的更多相关文章

  1. 120. 单词接龙 (BFS)

    描述 给出两个单词(start和end)和一个字典,找到从start到end的最短转换序列 比如: 每次只能改变一个字母. 变换过程中的中间单词必须在字典中出现. 如果没有转换序列则返回0. 所有单词 ...

  2. NOIP2000单词接龙[DFS]

    题目描述 单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合 ...

  3. Noip2000 T3 单词接龙

    题目描述 单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合 ...

  4. 洛谷 P1019 单词接龙 Label:dfs

    题目描述 单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合 ...

  5. 【wikioi】1018 单词接龙

    题目链接 算法:DFS+考你阅题 题目描述: 单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中 ...

  6. NOIP2000 单词接龙

    题三.  单词接龙                (27分)    问题描述    单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的 ...

  7. 1172: 单词接龙(XCOJ 暴力DFS)

    1172: 单词接龙 时间限制: 1 Sec  内存限制: 128 MB提交: 12  解决: 5 标签提交统计讨论版 题目描述 单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词 ...

  8. 单词接龙(dragon)

    单词接龙(dragon) 题目描述 单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次) ...

  9. NOIP2000提高组 单词接龙

    题目描述 单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的"龙"(每个单词都最多在"龙" ...

  10. 洛谷 P1019 单词接龙【经典DFS,温习搜索】

    P1019 单词接龙 题目描述 单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在 ...

随机推荐

  1. javascript node节点学习

    node节点学习 1 . 获取节点(元素)的方法 document.getElementById(); document.getElementsByTagName() document.getElem ...

  2. C++11 initializer_list 和 Range-based for loop 学习理解

    win10 + vs2017 源码如下: int main() { vector< int > numbers = { 1, 2, 3, 4, 5 }; for (auto num : n ...

  3. php实现姓名按首字母排序的类与方法

    php将名字按首字母进行排序 <?php public function getFirstChar($s){ $s0 = mb_substr($s,0,3); //获取名字的姓 $s = ico ...

  4. Spark异常:A master URL must be set in your configuration处理记录

    问题描述:    项目中一位同事提交了一部分代码,代码分为一个抽象类,里面含有sparkcontent,sparkSession对象:然后又三个子类实例化上述抽象类,这三个子类处理三个任务,最后在同一 ...

  5. 树莓派3B+学习笔记:8、安装MySQL

    1.打开终端,先执行: sudo apt-get update 2.再执行: sudo apt-get install mysql-server 输入“y”确认并回车 3.初始化MySQL,输入: s ...

  6. 解决Stm32出现error: #20: identifier "GPIO_InitTypeDef" is undefined异常

    该错误是我在移植sd卡程序时出现的,错误如下: error:#20,查看错误,可以发现,这些变量都是系统定义过的,没有修改过.并且该变量也能成功跳转被找到.那么到底是什么原因呢?逛了一些帖子,尝试了好 ...

  7. linux打patch简单示例

    在项目中,有些模块是开源的,没有源码或者不能改动源码,想要修复.优化里面的Bug,这时就需要用到patch了. 1.    生成patch 制作补丁有两种法法,diff和quilt. 1.1   di ...

  8. Myeclipse破解总结

    今天安装svn,Myeclipse莫名的崩了,然后就重装,然后不知为什么一直失败...经过无数次尝试,终于成功,应该是把这个破解过程遇到的所有问题都遇到了吧.有个别细节我没尝试,但以下总结用于Myec ...

  9. 20155224 实验一《Java开发环境的熟悉》实验报告

    实验内容 1.使用JDK编译.运行简单的Java程序: 2.使用Eclipse 编辑.编译.运行.调试Java程序. 实验要求 1.没有Linux基础的同学建议先学习<Linux基础入门(新版) ...

  10. [POI2011]MET-Meteors

    题面 题解 首先我们尝试暴力,那么就对每个点二分一下即可. 我们发现单独二分复杂度太高,而且有些地方很浪费,如求前缀和等. 那么我们就想,能否将它们合并在一起二分呢? 于是就有了整体二分 整体二分即可 ...