Word Ladder II

Given two words (start and end), and a dictionary, find all shortest transformation sequence(s) from start to end, such that:

Only one letter can be changed at a time
Each intermediate word must exist in the dictionary
For example,

Given:
start = "hit"
end = "cog"
dict = ["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.

SOLUTION 1:

这题做得真累,主页君差点一口老血吐在屏幕上,感觉一不小心就会超时了。

其实最后还是可以采用跟Word Ladder 1一样的解法。使用BFS遍历可能的解。不同的有以下几点:

1. 分层次遍历的时候,不要把找到的解的单词直接放在MAP中,而是可以放在别的一个临时的MAP中,一层遍历完成后,再统一加到MAP。这样做的上的是:

如果本层找到一个单词比如Word,本层的其它单词如果也可以到达Word,我们仍然要把它的解都记下来。

2. 添加到队列的时候,也要判断是不是一个新的单词(在临时MAP中查一下),是新的才能放在Queue中,否则因为1的关系,我们会计算某个单词的所有的解,所以会一直访问它。为了避免重复加入一个单词,这一步是有必要的。

3. 与Word Ladder1中的set不同,我们使用一个hasmap来记录路径中的单词,另外,每一个单词对应的value是一个string的list,记录到达此单词的所有的可能的路径。创建这些路径的方法是:把前节点的所有的路径加上当前单词,复制一份加过来即可。

REF: http://blog.csdn.net/whuwangyi/article/details/21611433

 public class Solution {
public static List<List<String>> findLadders(String start, String end, Set<String> dict) {
if (start == null || end == null) {
return null;
} Queue<String> q = new LinkedList<String>(); // 存储每一个单词对应的路径
HashMap<String, List<List<String>>> map = new HashMap<String, List<List<String>>>(); // 标记在某一层找到解
boolean find = false; // store the length of the start string.
int lenStr = start.length(); List<List<String>> list = new ArrayList<List<String>>(); // 唯一的路径
List<String> path = new ArrayList<String>();
path.add(start);
list.add(path); // 将头节点放入
map.put(start, list);
q.offer(start); while (!q.isEmpty()) {
int size = q.size(); HashMap<String, List<List<String>>> mapTmp = new HashMap<String, List<List<String>>>();
for (int i = 0; i < size; i++) {
// get the current word.
String str = q.poll();
for (int j = 0; j < lenStr; j++) {
StringBuilder sb = new StringBuilder(str);
for (char c = 'a'; c <= 'z'; c++) {
sb.setCharAt(j, c);
String tmp = sb.toString(); // 1. 重复的单词,不需要计算。因为之前一层出现过,再出现只会更长
// 2. 必须要在字典中出现
if (map.containsKey(tmp) || (!dict.contains(tmp) && !tmp.equals(end))) {
continue;
} // 将前节点的路径提取出来
List<List<String>> pre = map.get(str); // 从mapTmp中取出节点,或者是新建一个节点
List<List<String>> curList = mapTmp.get(tmp);
if (curList == null) {
// Create a new list and add to the end word.
curList = new ArrayList<List<String>>();
mapTmp.put(tmp, curList); // 将生成的单词放入队列,以便下一次继续变换
// 放在这里可以避免Q重复加入
q.offer(tmp);
} // 将PRE的path 取出,加上当前节点,并放入curList中
for(List<String> pathPre: pre) {
List<String> pathNew = new ArrayList<String>(pathPre);
pathNew.add(tmp);
curList.add(pathNew);
} if (tmp.equals(end)) {
find = true;
}
}
}
} if (find) {
return mapTmp.get(end);
} // 把当前层找到的解放在MAP中。
// 使用2个map的原因是:在当前层中,我们需要把同一个单词的所有的解全部找出来.
map.putAll(mapTmp);
} // 返回一个空的结果
return new ArrayList<List<String>>();
}
}

 2014.12.18 Redo:

做了一个小小的优化,拿掉了Find Flag:

 public class Solution {
public static List<List<String>> findLadders(String start, String end, Set<String> dict) {
List<List<String>> ret = new ArrayList<List<String>>();
if (start == null || end == null || dict == null) {
return ret;
} HashMap<String, List<List<String>>> map = new HashMap<String, List<List<String>>>(); // Store the map of the current level.
HashMap<String, List<List<String>>> mapTmp = new HashMap<String, List<List<String>>>(); Queue<String> q = new LinkedList<String>();
q.offer(start); List<List<String>> listStart = new ArrayList<List<String>>(); // 唯一的路径
List<String> path = new ArrayList<String>();
path.add(start);
listStart.add(path); // 将头节点放入
map.put(start, listStart); while (!q.isEmpty()) {
int size = q.size(); for (int i = 0; i < size; i++) {
String s = q.poll(); int len = s.length();
for (int j = 0; j < len; j++) {
StringBuilder sb = new StringBuilder(s);
for (char c = 'a'; c <= 'z'; c++) {
// Bug 2: should seperate the setCharAt(j, c) function and the sb.toString() function.
sb.setCharAt(j, c);
String tmp = sb.toString(); // 1. 不在字典中,并且不是end.
// 2. 前面的map中已经出现过 // Bug 1: map should use containsKey;
if ((!dict.contains(tmp) && !tmp.equals(end)) || map.containsKey(tmp)) {
continue;
} // Try to get the pre list.
List<List<String>> pre = map.get(s); // 从mapTmp中取出节点,或者是新建一个节点
List<List<String>> curList = mapTmp.get(tmp);
if (curList == null) {
curList = new ArrayList<List<String>>(); // Only offer new string to the queue.
// 将生成的单词放入队列,以便下一次继续变换
// 放在这里可以避免Q重复加入
q.offer(tmp); // create a new map.
mapTmp.put(tmp, curList);
} // 将PRE的path 取出,加上当前节点,并放入curList中
for (List<String> strList: pre) {
// Should create a new list.
List<String> strListNew = new ArrayList<String>(strList);
strListNew.add(tmp);
curList.add(strListNew);
}
}
}
} if (mapTmp.containsKey(end)) {
return mapTmp.get(end);
} // add the tmp map into the map.
map.putAll(mapTmp);
} return ret;
}
}

SOLUTION 2:

http://www.ninechapter.com/solutions/

GITHUB:

https://github.com/yuzhangcmu/LeetCode_algorithm/blob/master/string/FindLadders.java

https://github.com/yuzhangcmu/LeetCode_algorithm/blob/master/string/FindLadders_1218_2014.java

LeetCode: Word Ladder II 解题报告的更多相关文章

  1. LeetCode: Word Break II 解题报告

    Word Break II Given a string s and a dictionary of words dict, add spaces in s to construct a senten ...

  2. 【原创】leetCodeOj --- Word Ladder II 解题报告 (迄今为止最痛苦的一道题)

    原题地址: https://oj.leetcode.com/submissions/detail/19446353/ 题目内容: Given two words (start and end), an ...

  3. [leetcode]Word Ladder II @ Python

    [leetcode]Word Ladder II @ Python 原题地址:http://oj.leetcode.com/problems/word-ladder-ii/ 参考文献:http://b ...

  4. LeetCode :Word Ladder II My Solution

    Word Ladder II Total Accepted: 11755 Total Submissions: 102776My Submissions Given two words (start  ...

  5. 【LeetCode】Permutations II 解题报告

    [题目] Given a collection of numbers that might contain duplicates, return all possible unique permuta ...

  6. LeetCode: Unique Paths II 解题报告

    Unique Paths II Total Accepted: 31019 Total Submissions: 110866My Submissions Question Solution  Fol ...

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

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

  8. LeetCode: Word Ladder II [127]

    [题目] Given two words (start and end), and a dictionary, find all shortest transformation sequence(s) ...

  9. 【LeetCode】212. Word Search II 解题报告(C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 前缀树 日期 题目地址:https://leetco ...

随机推荐

  1. sqlserver profiler 抓出来作业的代码 SQLAgent - TSQL JobStep,二进制作业名字转化为字段串作业名字,job_id

    sqlserver 中 profiler 抓出来不少是作业中的代码,applicationname 类似于 SQLAgent - TSQL JobStep (Job 0x94B9B5C016E8D94 ...

  2. Java之异常机制(1) - 高效处理异常

    Java开发人员做出的有关架构的最重要的决定之一便是如何使用Java异常模型.Java异常处理成为社区中讨论最多的话题之一.一些人认为Java语 言中的已检查异常(Checked Exceptions ...

  3. HTTP 304状态分析

       在看http log日志发现很多304状态的标识 HTTP 304: Not Modified   ###请求后读取本地缓存的文件标准解释是:Not Modified 客户端有缓冲的文档并发出了 ...

  4. 开源大数据技术专场(上午):Spark、HBase、JStorm应用与实践

    16日上午9点,2016云栖大会“开源大数据技术专场” (全天)在阿里云技术专家封神的主持下开启.通过封神了解到,在上午的专场中,阿里云高级技术专家无谓.阿里云技术专家封神.阿里巴巴中间件技术部高级技 ...

  5. 使用c:forEach 控制5个换行

    今天做项目的时候碰到一个问题,我须要显示不确定数目的图片在网页上(图片是从数据库查出来的),用的是<c:forEach>循环取值的.就须要做成一行显示固定个数的图片.代码例如以下(我这里是 ...

  6. Outlook如何定时发邮件

    http://jingyan.baidu.com/article/c843ea0b63e15377931e4a0e.html 更多文章: Outlook定时发送邮件问题-http://blog.sin ...

  7. window下删除所有带.svn文件夹及文件,删除所有的.svn文件夹

    (一)------------------------------------------------------------------------------------------------- ...

  8. Android开发学习之3大类菜单

    在Android系统中,菜单可以分为三类:选项菜单(Option Menu),上下文菜单(Context Menu)以及子菜单(Sub Menu). 一.选项菜单(Option Menu) 创建选项菜 ...

  9. 页面livereload width grunt

    step-1.   安装node 环境 step-2.  npm  install grunt-cli  \ grunt http://www.gruntjs.net/docs/getting-sta ...

  10. SSAS多维数据集以及维度的建立

    首先打开vs建立一个Analysis Services项目,然后点击数据源文件右键[新建数据源],根据数据源向导建立自己的数据源,如图1: 点击[确定],选择刚才的数据连接,点击[下一步]进入模拟信息 ...