[LeetCode] Word Ladder 词语阶梯
Given two words (beginWord and endWord), and a dictionary's word list, find the length of shortest transformation sequence from beginWord to endWord, such that:
- Only one letter can be changed at a time.
- Each transformed word must exist in the word list. Note that beginWord is not a transformed word.
Note:
- Return 0 if there is no such transformation sequence.
- All words have the same length.
- All words contain only lowercase alphabetic characters.
- You may assume no duplicates in the word list.
- You may assume beginWord and endWord are non-empty and are not the same.
Example 1:
Input:
beginWord = "hit",
endWord = "cog",
wordList = ["hot","dot","dog","lot","log","cog"] Output: 5 Explanation: As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog",
return its length 5.
Example 2:
Input:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log"] Output: 0 Explanation: The endWord "cog" is not in wordList, therefore no possible transformation.
这道词句阶梯的问题给了我们一个单词字典,里面有一系列很相似的单词,然后给了一个起始单词和一个结束单词,每次变换只能改变一个单词,并且中间过程的单词都必须是单词字典中的单词,让我们求出最短的变化序列的长度。这道题还是挺有难度的,我当然是看了别人的解法才写出来的,这没啥的,从不会到完全掌握才是成长嘛~
当拿到题就懵逼的我们如何才能找到一个科学的探索解题的路径呢,那就是先别去管代码实现,如果让我们肉身解题该怎么做呢?让你将 'hit' 变为 'cog',那么我们发现这两个单词没有一个相同的字母,所以我们就尝试呗,博主会先将第一个 'h' 换成 'c',看看 'cit' 在不在字典中,发现不在,那么把第二个 'i' 换成 'o',看看 'hot' 在不在,发现在,完美!然后尝试 'cot' 或者 'hog',发现都不在,那么就比较麻烦了,我们没法快速的达到目标单词,需要一些中间状态,但我们怎么知道中间状态是什么。简单粗暴的方法就是brute force,遍历所有的情况,我们将起始单词的每一个字母都用26个字母来替换,比如起始单词 'hit' 就要替换为 'ait', 'bit', 'cit', .... 'yit', 'zit',将每个替换成的单词都在字典中查找一下,如果有的话,那么说明可能是潜在的路径,要保存下来。那么现在就有个问题,比如我们换到了 'hot' 的时候,此时发现在字典中存在,那么下一步我们是继续试接下来的 'hpt', 'hqt', 'hrt'... 还是直接从 'hot' 的首字母开始换 'aot', 'bot', 'cot' ... 这实际上就是BFS和DFS的区别,到底是广度优先,还是深度优先。讲到这里,不知道你有没有觉得这个跟什么很像?对了,跟迷宫遍历很像啊,你想啊,迷宫中每个点有上下左右四个方向可以走,而这里有26个字母,就是二十六个方向可以走,本质上没有啥区别啊!如果熟悉迷宫遍历的童鞋们应该知道,应该用BFS来求最短路径的长度,这也不难理解啊,DFS相当于一条路走到黑啊,你走的那条道不一定是最短的啊。而BFS相当于一个小圈慢慢的一层一层扩大,相当于往湖里扔个石头,一圈一圈扩大的水波纹那种感觉,当水波纹碰到湖上的树叶时,那么此时水圈的半径就是圆心到树叶的最短距离。脑海中有没有浮现出这个生动的场景呢?
明确了要用BFS,我们可以开始解题了,为了提到字典的查找效率,我们使用HashSet保存所有的单词。然后我们需要一个HashMap,来建立某条路径结尾单词和该路径长度之间的映射,并把起始单词映射为1。既然是BFS,我们需要一个队列queue,把起始单词排入队列中,开始队列的循环,取出队首词,然后对其每个位置上的字符,用26个字母进行替换,如果此时和结尾单词相同了,就可以返回取出词在哈希表中的值加一。如果替换词在字典中存在但在哈希表中不存在,则将替换词排入队列中,并在哈希表中的值映射为之前取出词加一。如果循环完成则返回0,参见代码如下:
解法一:
class Solution {
public:
int ladderLength(string beginWord, string endWord, vector<string>& wordList) {
unordered_set<string> wordSet(wordList.begin(), wordList.end());
if (!wordSet.count(endWord)) return ;
unordered_map<string, int> pathCnt{{{beginWord, }}};
queue<string> q{{beginWord}};
while (!q.empty()) {
string word = q.front(); q.pop();
for (int i = ; i < word.size(); ++i) {
string newWord = word;
for (char ch = 'a'; ch <= 'z'; ++ch) {
newWord[i] = ch;
if (wordSet.count(newWord) && newWord == endWord) return pathCnt[word] + ;
if (wordSet.count(newWord) && !pathCnt.count(newWord)) {
q.push(newWord);
pathCnt[newWord] = pathCnt[word] + ;
}
}
}
}
return ;
}
};
其实我们并不需要上面解法中的HashMap,由于BFS的遍历机制就是一层一层的扩大的,那么我们只要记住层数就行,然后在while循环中使用一个小trick,加一个for循环,表示遍历完当前队列中的个数后,层数就自增1,这样的话我们就省去了HashMap,而仅仅用一个变量res来记录层数即可,参见代码如下:
解法二:
class Solution {
public:
int ladderLength(string beginWord, string endWord, vector<string>& wordList) {
unordered_set<string> wordSet(wordList.begin(), wordList.end());
if (!wordSet.count(endWord)) return ;
queue<string> q{{beginWord}};
int res = ;
while (!q.empty()) {
for (int k = q.size(); k > ; --k) {
string word = q.front(); q.pop();
if (word == endWord) return res + ;
for (int i = ; i < word.size(); ++i) {
string newWord = word;
for (char ch = 'a'; ch <= 'z'; ++ch) {
newWord[i] = ch;
if (wordSet.count(newWord) && newWord != word) {
q.push(newWord);
wordSet.erase(newWord);
}
}
}
}
++res;
}
return ;
}
};
类似题目:
参考资料:
https://leetcode.com/problems/word-ladder/description/
https://leetcode.com/problems/word-ladder/discuss/40728/Simple-Java-BFS-solution-with-explanation
LeetCode All in One 题目讲解汇总(持续更新中...)
[LeetCode] Word Ladder 词语阶梯的更多相关文章
- [Leetcode] word ladder 单词阶梯
Given two words (start and end), and a dictionary, find the length of shortest transformation sequen ...
- LeetCode:Word Ladder I II
其他LeetCode题目欢迎访问:LeetCode结题报告索引 LeetCode:Word Ladder Given two words (start and end), and a dictiona ...
- [leetcode]Word Ladder II @ Python
[leetcode]Word Ladder II @ Python 原题地址:http://oj.leetcode.com/problems/word-ladder-ii/ 参考文献:http://b ...
- [LeetCode] Word Ladder II 词语阶梯之二
Given two words (start and end), and a dictionary, find all shortest transformation sequence(s) from ...
- [LeetCode] 127. Word Ladder 单词阶梯
Given two words (beginWord and endWord), and a dictionary's word list, find the length of shortest t ...
- LeetCode :Word Ladder II My Solution
Word Ladder II Total Accepted: 11755 Total Submissions: 102776My Submissions Given two words (start ...
- LeetCode: Word Ladder II 解题报告
Word Ladder II Given two words (start and end), and a dictionary, find all shortest transformation s ...
- LeetCode: Word Ladder II [127]
[题目] Given two words (start and end), and a dictionary, find all shortest transformation sequence(s) ...
- LeetCode Word Ladder 找单词变换梯
题意:给出两个单词,以及一个set集合,当中是很多的单词.unordered_set是无序的集合,也就是说找的序列也是无序的了,是C++11的标准,可能得升级你的编译器版本了.要求找出一个从start ...
随机推荐
- ASP.NET Core 中文文档 第二章 指南(4.5)使用 SQL Server LocalDB
原文:Working with SQL Server LocalDB 作者:Rick Anderson 翻译: 魏美娟(初见) 校对: 孟帅洋(书缘).张硕(Apple).许登洋(Seay) Appl ...
- oracle函数案例以及分页案例
--日期函数select sysdate from dual--返回两个日期select months_between(to_date('2017-1-7','yyyy-mm-dd'),to_date ...
- C++进程间通信
# C++进程间通信 # 进程间通讯的四种方式:剪贴板.匿名管道.命名管道和邮槽 ## 剪切板 ## //设置剪切板内容 CString str; this->GetDlgItemText(ID ...
- ASP.NET Core File Providers
原文地址:FileProvider By Steve Smith ASP.NET Core通过对File Providers的使用实现了对文件系统访问的抽象. 查看或下载示例代码 File Provi ...
- spring笔记5 spring IOC的基础知识1
1,ioc的概念 Inverse of control ,控制反转,实际的意义是调用类对接口实现类的依赖,反转给第三方的容器管理,从而实现松散耦合: ioc的实现方式有三种,属性注入,构造函数注入,接 ...
- js 隐式转换
1.数字number与字符串string相加的就,最后会得到一个字符串string:'1'+3='13' 2.数字number与字符串string相减,最后会得到一个数字number:'1'-0=1, ...
- js条件判断时隐式类型转换
Javascript 中,数字 0 为假,非0 均为真 在条件判断运算 == 中的转换规则是这样的: 如果比较的两者中有布尔值(Boolean),会把 Boolean 先转换为对应的 Number,即 ...
- low security dvwa--SQL Injection(Blind)
1.输入单引号,结果如下: 2.输入永真式 ' and 1=1; -- 结果如下: 多次测试,如果输入的条件为假,就会返回1中的结果,为真则返回2中的结果,由此说明这属于SQL盲注. 3.猜解用户名长 ...
- DarkTrack 4 Alien Version Released RAT 下载地址&视频教程
不废话,点我下载. 官方论坛:https://forum.darktrack.net 作者脸书:https://www.facebook.com/darktrackrat E安全报道:https:// ...
- VS2012 Unit Test——Microsoft Fakes入门
如题,本文主要作为在VS2012使用Fakes的入门示例,开发工具必须是VS2012或更高版本. 关于Fakes的MSDN地址:http://msdn.microsoft.com/en-us/libr ...