126. Word Ladder II
题目:
Given two words (beginWord and endWord), and a dictionary's word list, find all shortest transformation sequence(s) from beginWord to endWord, such that:
- Only one letter can be changed at a time
- Each intermediate word must exist in the word list
For example,
Given:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log"]
Return
[
["hit","hot","dot","dog","cog"],
["hit","hot","lot","log","cog"]
]
Note:
- All words have the same length.
- All words contain only lowercase alphabetic characters.
链接: https//leetcode.com/problems/word-ladder-ii/
题解:
求所有最短路径...第一想法是先定义一个用adjacent list表示的图类,然后用Dijkstra求最短路径们。
再仔细想一想,我们现在应该有两条路,一条是在Word Ladder I的基础上改进, 另外一条是用一个不太一样的方法从头思考设计和解决。
先试试第一条,在Word Ladder I基础上改进。一个可能的解法基本步骤可能是:
- 按照Word Ladder I的方法,用BFS求最段路径
- 找到第一条最短路径的时候,不返回,继续计算Queue里这一层BFS其他结点,看是否能有其他最短路径。 因为在这一层找到了最短路径,所以长度是固定的,找完这一层就可以结束了,返回结果。
- 在每一层BFS的时候cache之前路径。对于 visited的处理,在每一层运算结束之后再统一更新visited,否则如果下一节点由这一层的多个节点共用,会出问题。
- 如何保存已经访问过的节点。比如假设用 HashMap<String, List<String>>来保存下一节点与之前路径,假设有一条为 tex, {red,ted,tex},还有一条 tex,{red,rex,tex},这时就有了collision。所以可能只能储存前序的节点,并不能保存整个路径,除非额外做些处理,比如另外做数据结构,或者把路径做成 word + delimiter,然后比较的时候取split string得到的数组里的最后一个元素, 之类的。
- 只存前序节点的话,最后的结果应该是在HashMap里的一条<endWord, List<String>>。 这样再从endWord开始对List<String>做一个DFS,应该就可以找到所要求的路径。
12:53AM,尝试完毕,可以作为一个解。要继续研究最优解法。终于AC了好高兴,基本算是做了整整一天。写的代码丑陋异常...一定要再优化优化。复杂度应该和1一样,不过代码里面用到了list的contains,也许会增加一些低阶量。
Time Complexity - O(min(26^L, size(wordList)), Space Complexity - O(min(26^L, size(wordList)), L为 word length。
public class Solution {
public List<List<String>> findLadders(String beginWord, String endWord, Set<String> wordList) {
List<List<String>> res = new ArrayList<>();
if(beginWord == null || endWord == null || wordList == null || wordList.size() == 0 || beginWord.equals(endWord))
return res;
if(wordList.contains(beginWord))
wordList.remove(beginWord);
if(wordList.contains(endWord))
wordList.remove(endWord); Queue<String> q = new LinkedList<>();
q.offer(beginWord);
int curLevel = 1, nextLevel = 0;
HashSet<String> visited = new HashSet<>();
HashSet<String> levelVisited = new HashSet<>();
HashMap<String, ArrayList<String>> wordChains = new HashMap<>();
boolean foundShortestPath = false; while(!q.isEmpty()) {
String word = q.poll();
curLevel--; for(int i = 0; i < word.length(); i++) {
char[] wordAsArray = word.toCharArray(); for(char j = 'a'; j <= 'z'; j++) {
wordAsArray[i] = j;
String newWord = String.valueOf(wordAsArray); if(newWord.equals(endWord)) { // found shortest path at this level
foundShortestPath = true; // flag to only process this level, then return
if(wordChains.containsKey(endWord)) {
if(!wordChains.get(endWord).contains(word))
wordChains.get(endWord).add(word);
} else {
ArrayList<String> preWords = new ArrayList<>();
preWords.add(word);
wordChains.put(endWord, preWords);
}
break;
} if(wordList.contains(newWord) && !visited.contains(newWord)) { //found edge to next node
q.offer(newWord);
if(wordChains.containsKey(newWord)) {
if(!wordChains.get(newWord).contains(word))
wordChains.get(newWord).add(word);
} else {
ArrayList<String> preWords = new ArrayList<>();
preWords.add(word);
wordChains.put(newWord, preWords);
}
nextLevel++;
levelVisited.add(newWord); //add the newWord to a temp visited HashMap
}
}
} if(curLevel == 0) {
if(foundShortestPath)
break;
curLevel = nextLevel;
nextLevel = 0;
for(String str : levelVisited) //update the global "visited"
visited.add(str);
levelVisited.clear();
}
} ArrayList<String> list = new ArrayList<>();
list.add(endWord);
getWordChains(res, list, wordChains, beginWord, endWord);
return res;
} private void getWordChains(List<List<String>> res, ArrayList<String> list, HashMap<String, ArrayList<String>> wordChains, String beginWord, String endWord) {
if(endWord.equals(beginWord)) {
res.add(new ArrayList<String>(list));
return;
}
ArrayList<String> curLevel= new ArrayList<>();
if(wordChains.containsKey(endWord))
curLevel = wordChains.get(endWord);
else
return; for(int i = 0; i < curLevel.size(); i++) {
String word = curLevel.get(i);
list.add(0, word);
getWordChains(res, list, wordChains, beginWord, word);
list.remove(word);
}
}
}
再试试第二条(刷下一遍时)
急需学习图的各种知识。WordLadder这种经典题目,Sedgewick的算法书和Mark Ellen Weiss的数据结构书里都有涉及,要多学多练。
题外话: 中午去SOHO和Justin谈了一下,他说有3个startup不错,一个是doubleclick前CEO做的,专门搞古董交易的startup。第二个是ADP sponsor的internal子公司,做得很像zenefits。第三个是一个做男士剃须刀的,有专门的厂家在德国,目标是在你需要刮胡子的时候快递新的刮胡刀上门。真的很有意思,broaden my vision。 下午继续回公司做事,要处理好和同事,上级的关系,要有耐心,不要急躁。
Reference:
http://baike.baidu.com/view/349189.htm
https://zh.wikipedia.org/wiki/%E6%9C%80%E7%9F%AD%E8%B7%AF%E9%97%AE%E9%A2%98
http://blog.csdn.net/v_july_v/article/details/6181485
http://www.geeksforgeeks.org/breadth-first-traversal-for-a-graph/
http://algs4.cs.princeton.edu/code/edu/princeton/cs/algs4/Graph.java.html
http://www.cnblogs.com/springfor/p/3893529.html
http://blog.csdn.net/linhuanmars/article/details/23071455
126. Word Ladder II的更多相关文章
- 126. Word Ladder II(hard)
126. Word Ladder II 题目 Given two words (beginWord and endWord), and a dictionary's word list, find a ...
- leetcode 127. Word Ladder、126. Word Ladder II
127. Word Ladder 这道题使用bfs来解决,每次将满足要求的变换单词加入队列中. wordSet用来记录当前词典中的单词,做一个单词变换生成一个新单词,都需要判断这个单词是否在词典中,不 ...
- [LeetCode] 126. Word Ladder II 词语阶梯之二
Given two words (beginWord and endWord), and a dictionary's word list, find all shortest transformat ...
- Java for LeetCode 126 Word Ladder II 【HARD】
Given two words (start and end), and a dictionary, find all shortest transformation sequence(s) from ...
- [LeetCode] 126. Word Ladder II 词语阶梯 II
Given two words (beginWord and endWord), and a dictionary's word list, find all shortest transformat ...
- LeetCode 126. Word Ladder II 单词接龙 II(C++/Java)
题目: Given two words (beginWord and endWord), and a dictionary's word list, find all shortest transfo ...
- leetcode 126. Word Ladder II ----- java
Given two words (beginWord and endWord), and a dictionary's word list, find all shortest transformat ...
- Leetcode#126 Word Ladder II
原题地址 既然是求最短路径,可以考虑动归或广搜.这道题对字典直接进行动归是不现实的,因为字典里的单词非常多.只能选择广搜了. 思路也非常直观,从start或end开始,不断加入所有可到达的单词,直到最 ...
- 【leetcode】126. Word Ladder II
题目如下: 解题思路:DFS或者BFS都行.本题的关键在于减少重复计算.我采用了两种方法:一是用字典dic_ladderlist记录每一个单词可以ladder的单词列表:另外是用dp数组记录从star ...
随机推荐
- Poj 3030 Nasty Hacks
1.Link: http://poj.org/problem?id=3030 2.Content: Nasty Hacks Time Limit: 1000MS Memory Limit: 655 ...
- json-lib-2.4.jar Bug,json字符串中value为"[value]"结构时,解析为数组,不会解析成字符串
使用json-lib.jar 2.4进行json字符串转换为对象时发现一个bug.贴下测试代码: <dependency> <groupId>net.sf.json-lib&l ...
- CocoaPods安装和使用及问题:Setting up CocoaPods master repo
CocoaPods是什么? 当你开发iOS应用时,会经常使用到很多第三方开源类库,比如JSONKit,AFNetWorking等等.可能某个类库又用到其他类库,所以要使用它,必须得另外下载其他类库,而 ...
- 弹性布局学习-详解align-content(六)
弹性布局学习-详解align-content(六)
- 51nod1212无向图最小生成树
1212 无向图最小生成树 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 收藏 关注 N个点M条边的无向连通图,每条边有一个权值,求该图的最小生成树. Inpu ...
- php数组去重实例及分析
php数组去重实例及分析. 一维数组的重复项: 使用array_unique函数即可,使用实例 <?php $aa=array("apple","banan ...
- Ecshop实现仿Taobao地区运费模板
目录: 1.Ecshop后台配送方式创建 2.商品绑定配送方式的运费模板 2.1 数据表“ecs_goods”增加一个字段,执行下面SQL语句: 2.2 后台添加/编辑 商品 调出已经安装配送方式 & ...
- CorelDRAW 插件的安装和使用
CorelDRAW 是一款在中国非常受欢迎的图形软件,开放的界面和编程技术,能够对它进行二次开发制作插件,插件大抵有三种gms.cpg.exe格式,下面介绍一下这三种插件的安装和使用方法. 一.gms ...
- MS也遵守规范了
CSS学的好不好,就看你对浏览器的兼容性处理的好不好. 拿opacity来说,本来写成opacity:0.3就完事了,但MS不来这套,它用filter,我们就不得不专门为它而 加上这么一大串(file ...
- hdu 5343 MZL's Circle Zhou SAM
MZL's Circle Zhou 题意:给定两个长度不超过a,b(1 <= |a|,|b| <= 90000),x为a的连续子串,b为y的连续子串(x和y均可以是空串):问x+y形成的不 ...