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

  1. Only one letter can be changed at a time
  2. 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.

难度挺高的一题。沿用Word Ladder I的思路,此题本质也是图的遍历问题,求的是从给定起点到给定终点之间的所有最短路径。

Word Ladder I 中,找到一条合法路径即返回。然而此题中找到一条之后还需要进行讨论,问题就变复杂了,因为广度优先遍历中之前的节点都已经出队列没法再获取到。

所以,沿用Word Ladder I中的思想,不仅记录每个结点距离start的距离,而且用List记录这个到达这个节点的所有最短路径上的前驱结点。举个例子:

6的List应当为 2 和 3, 因为5 不是最短路径上的点。

这里采用HashMap去处理结点和List的映射关系。

这样在进行广度优先遍历过程中,会有以下几种情况:

1. 相邻结点新结点,那么新结点入队列;建立新结点的List和,把当前结点加入到新结点的List中;记录新结点的最短路径长度为当前结点的最短路径长度L+1

2. 相邻结点在队列中(例如上图结点3出队列时,6还在队列中)且相邻结点的最短路径长度=当前结点最短路径长度+1,那么说明是另一条最短路径,只需要把当前结点加入到相邻结点的List中。

3. 相邻结点在队列中且相邻结点的最短路径长度<当前结点最短路径长度+1,说明这条不是最短路径,那么什么也不做,当前结点默默出队列。

这样我们可以得到从start到end的若干条链,从end开始逆向使用回溯法记录所有的链上的结点即可。

代码如下:

     HashMap<String, ArrayList<String>> nodeSet = new HashMap<String, ArrayList<String>>();
public List<List<String>> findLadders(String start, String end, Set<String> dict) {
List<List<String>> re = new ArrayList<List<String>>();
Queue<String> q = new LinkedList<String>();
HashSet<String> hs = new HashSet<String>();
HashMap<String, Integer> dist = new HashMap<String, Integer>();
q.add(start);
nodeSet.put(start, new ArrayList<String>());
nodeSet.put(end, new ArrayList<String>());
dist.put(start, 1); while(!q.isEmpty()) {
String temp = q.poll();
int l = dist.get(temp);
hs.add(temp);
for(int i=0;i<temp.length();i++) {
for(char c='a';c<='z';c++) {
if(temp.charAt(i)==c)
continue;
StringBuilder sb = new StringBuilder(temp);
sb.setCharAt(i,c);
String next = sb.toString();
if(next.equals(end)) {
if(!dist.containsKey(end)) {
dist.put(end,l+1);
nodeSet.get(end).add(temp);
}
else if(dist.get(end)==l+1)
nodeSet.get(end).add(temp);
}
else if(dict.contains(next) && !hs.contains(next)) {
if(!dist.containsKey(next)) {
q.add(next);
dist.put(next, l+1);
ArrayList<String> arr = new ArrayList<String>();
arr.add(temp);
nodeSet.put(next, arr);
} else if(dist.get(next)==l+1)
nodeSet.get(next).add(temp);
}
}
}
}
List<String> path = new ArrayList<String>();
path.add(end);
collect(start,re,path,nodeSet.get(end));
return re;
}
public void collect(String start, List<List<String>> re, List<String> path, ArrayList<String> prevNodes)
{
for(int i=0;i<prevNodes.size();i++)
{
path.add(0,prevNodes.get(i));
if(prevNodes.get(i).equals(start)) {
List<String> pathCopy = new ArrayList<String>(path);
re.add(pathCopy);
}
else
collect(start,re,path,nodeSet.get(prevNodes.get(i)));
path.remove(0);
}
}

[Leetcode][JAVA] Word Ladder II的更多相关文章

  1. Java for LeetCode 126 Word Ladder II 【HARD】

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

  2. LeetCode 126. Word Ladder II 单词接龙 II(C++/Java)

    题目: Given two words (beginWord and endWord), and a dictionary's word list, find all shortest transfo ...

  3. [Leetcode Week5]Word Ladder II

    Word Ladder II 题解 原创文章,拒绝转载 题目来源:https://leetcode.com/problems/word-ladder-ii/description/ Descripti ...

  4. [LeetCode] 126. Word Ladder II 词语阶梯 II

    Given two words (beginWord and endWord), and a dictionary's word list, find all shortest transformat ...

  5. 【leetcode】Word Ladder II

      Word Ladder II Given two words (start and end), and a dictionary, find all shortest transformation ...

  6. [LeetCode#128]Word Ladder II

    Problem: Given two words (start and end), and a dictionary, find all shortest transformation sequenc ...

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

    Given two words (beginWord and endWord), and a dictionary's word list, find all shortest transformat ...

  8. leetcode 126. Word Ladder II ----- java

    Given two words (beginWord and endWord), and a dictionary's word list, find all shortest transformat ...

  9. Leetcode#126 Word Ladder II

    原题地址 既然是求最短路径,可以考虑动归或广搜.这道题对字典直接进行动归是不现实的,因为字典里的单词非常多.只能选择广搜了. 思路也非常直观,从start或end开始,不断加入所有可到达的单词,直到最 ...

随机推荐

  1. uploadify图片上传发生Security Error

    今天在使用uploadify进行图片上传的时候出现security error.其根本原因是flash跨域问题.主要原因是因为配了两个域名www.ttyouni.com 和 ttyouni.com 在 ...

  2. MSSQLSERVER之发布-分发-订阅

    一.环境 发布服务器 O S: Windows servier 2003 64位 Soft: Microsoft SqlServer 2008 R2 I P: 192.168.3.70 HOST-NA ...

  3. Python isdigit()方法

    描述 Python isdigit() 方法检测字符串是否只由数字组成. 语法 isdigit()方法语法: str.isdigit() 参数 无. 返回值 如果字符串只包含数字则返回 True 否则 ...

  4. css设置中文字体(font-family:"黑体")后样式失效问题

    做项目时偶遇的一诡异问题,同样的代码,在ff和IE7以上页面显示正常,但IE6无论怎么改都不起作用,本来以为是IE6的某些浮动bug所致,结果弄了很长时间也不行,后来不经意间把原来设定的font-fa ...

  5. MS SQL Server之光标、存储过程和触发器

    光标 通常数据库操作被认为是以数据集为基础的操作,但是光标被用于以记录为单位来进行操作,来获取数据库中的数据的子集.光标一般用于过程化程序里的嵌入的SQL语句. 对光标的定义如下: DECLARE C ...

  6. spring结合Quartz的集群功能实现

    一:前沿 在上一篇(http://www.cnblogs.com/wuhao1991/p/4331613.html)的博客中记载了定时的功能,但是集成是没有成功的,在这篇中,我在解释下这里的”集成的含 ...

  7. java.io.Serializable 序列化问题

    java.io.Serializable 序列化问题 Person.java package a.b.c; public class Person implements java.io.Seriali ...

  8. C#枚举描述获取

    public static class EnumExtension    {        public static string GetDescription(this Enum value)   ...

  9. MSVC 报错 unable to use inline in declaration get error C2054

    晚上用cmake生成了一份lua-cjson的工程文件,msvc6的 编译时报错 后来再stackoverflow找到答案:unable to use inline in declaration ge ...

  10. Linux下apache日志分析与状态查看方法

    假设apache日志格式为:118.78.199.98 – - [09/Jan/2010:00:59:59 +0800] “GET /Public/Css/index.css HTTP/1.1″ 30 ...