赞
踩
按字典 wordList 完成从单词 beginWord 到单词 endWord 转化,一个表示此过程的 转换序列 是形式上像 beginWord -> s1 -> s2 -> … -> sk 这样的单词序列,并满足:
给你两个单词 beginWord 和 endWord ,以及一个字典 wordList 。请你找出并返回所有从 beginWord 到 endWord 的 最短转换序列,如果不存在这样的转换序列,返回一个空列表。每个序列都应该以单词列表 [beginWord, s1, s2, …, sk] 的形式返回。
示例 1:
输入:beginWord = “hit”, endWord = “cog”, wordList = [“hot”,“dot”,“dog”,“lot”,“log”,“cog”]
输出:[[“hit”,“hot”,“dot”,“dog”,“cog”],[“hit”,“hot”,“lot”,“log”,“cog”]]
解释:存在 2 种最短的转换序列:
“hit” -> “hot” -> “dot” -> “dog” -> “cog”
“hit” -> “hot” -> “lot” -> “log” -> “cog”
示例 2:
输入:beginWord = “hit”, endWord = “cog”, wordList = [“hot”,“dot”,“dog”,“lot”,“log”]
输出:[]
解释:endWord “cog” 不在字典 wordList 中,所以不存在符合要求的转换序列。
提示:
该题目的简单类型在上篇文章 leetcode 127. 单词接龙 中进行了详细的分析,要看详细的分析请看上篇分析。那么这篇文章在上篇文章的基础上进行了修改,并添加了记录路径的方法。
解题方案:
(1)同样使用双向BFS的方法,每次从队列长度小的一端开始搜索。(2)在对某一层BFS开始之前,先将队列中的全部元素进行标记(至于为什么这么做,后边会解释)。(3)然后开始BFS,如果遍历到的节点未被标记,那么将该节点放入队列中,如果该节点存在于另一个队列中,说明已经找到最短的路径了。(4)此时将该层节点遍历结束后,方可进行回溯记录路径。(5)此外,需要在遍历节点的时候,通过判断这次遍历是从后向前还是从前向后,以确定构建的图的起始节点和结束节点。
(2)在对某一层BFS开始之前,先将队列中的全部元素进行标记。
假设遍历到了上图标记的位置,此时队列中的元素为 [ dot, lot] ,再次向后遍历的话,因为 dog 和 hot 都与 dot 相连,那么这两个元素都会入队列,可 hot 入队之后,程序的运行就会产生一个环形结构,这会对程序运行效率是极其不友好的,像这种情况,我们希望的是只将 dog 入队。因此,在程序开始之处,通过 wordList 构建一个wordListSet集合,集合中是全部未遍历过的元素。当队列中的元素是橘黄色指针指向的位置的时候,先将队列中的全部元素从wordListSet中删除(表示上一层的元素全部访问过),然后再遍历后边一层的元素(即:dog和log)后边一层中,只有存在于wordListSet中的元素才能入队。
(5)回溯建图
如上图所示,假设遍历到了箭头指向的位置(将hot从队列中弹出,并将[dot, lot]放入队列中),如果我们从正方向遍历的时候,map<key, val>
中的 key 就是 hot , val 就是[dot, lot],即 map<hot, [dot, lot]>
如上图所示,假设遍历到了箭头指向的位置(将log从队列中弹出并将lot放入队列中),如果从反方向遍历的时候,map<key, val>
中的 key 就是 lot , val 就是 log,即 map<lot, log>
。
public List<List<String>> findLadders(String beginWord, String endWord, List<String> wordList) {
wordList.add(beginWord);
// 构建一个标记集合,开始的时候,每个word都在集合中。后边每次将元素放到队列中,便将该元素从集合中删除,以实现标记功能
Set<String&
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。