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.

题解:算是leetcode最恶心的一道题了。

Word Ladder一样要用BFS来搜索,但是要解决的问题是如何在BFS中保存路径。我们知道在DFS中 保存路径十分简单,但是在BFS中就很麻烦了。因为我们把点一层一层的放在队列里面,而不是一次把一条路径搜索完全。所以这里引进一种新的类Node如下:

class Node{
ArrayList<Node> prev;
String me;
int dist;
public Node(String me,int dist){
this.me = me;
this.prev = null;
this.dist = dist;
}
}

使用该类,我们把搜索路径上遇到的每一个单词看成一个节点,me保存该节点对应的单词,dist保存从start单词搜索到该单词的最短距离,prev保存从start到该节点所有长度为dist的路径上该节点的前驱节点。

这样我们就可以在完成BFS后,从最后一个节点endNode(endNode对应单词end),利用前驱节点信息DFS出startNode到endNode的所有路径了。函数findPath实现这个功能。

另外在BFS的时候,我们需要一个map,来记录当前访问过哪些单词以及它们对应的节点。假设当前访问的节点是node,它对应的单词是t,我们通过修改t的每一位字母生成新的单词,如果新的单词在dict中且没有建立相应的节点(在map中没有记录),那么就建立相应的节点,并把该节点和单词的对应信息保存在map里面;如果当前生成的单词在dict中且已经有相应的节点,那么我们就看是否node也是它的前驱,如果是,把node加入它的前驱列表就可以了。

结束的条件是,我们生成了一个单词,它正好等于end,说明找到了从start到end的一条路径(不过为了找到所有到end的路径,所以当前队列中的元素还是要遍历完,因为它们在同一层上,也有可能可以达到end,所以用一个stop变量控制最外层的大循环);或者队列为空,说明找不到从start到end的路径。

最后代码如下:

 public class Solution {
private List<List<String>> answer= new ArrayList<List<String>>();
class Node{
ArrayList<Node> prev;
String me;
int dist;
public Node(String me,int dist){
this.me = me;
this.prev = null;
this.dist = dist;
}
}
private void findPath(Node endNode,ArrayList<String> result,String start){
if(endNode.me.equals(start)){
ArrayList<String> temp= new ArrayList<String>(result);
answer.add(temp);
return;
}
for(Node n:endNode.prev){
result.add(0, n.me);
findPath(n, result, start);
result.remove(0);
}
}
public List<List<String>> findLadders(String start, String end, Set<String> dict) { if(start == end){
List<String> result = new ArrayList<String>();
result.add(start);
result.add(end);
answer.add(result);
return answer;
} Queue<Node> queue = new LinkedList<Node>();
HashMap<String, Node> map = new HashMap<String,Node>(); Node startNdoe = new Node(start,0);
queue.add(startNdoe);
map.put(start, startNdoe);
Node endNode = null;
int strLen = start.length();
boolean stop = false; while(!queue.isEmpty() && !stop){
int thisLevel = queue.size();
for(int i = 0;i < thisLevel;i++){
Node node = queue.poll();
for(int j = 0;j < strLen;j++){
StringBuilder t = new StringBuilder(node.me);
char ch_t = node.me.charAt(j);
for(char k = 'a';k <= 'z';k++){
if(k != ch_t){
t.setCharAt(j, k);
if(dict.contains(t.toString())){
Node v = map.get(t.toString());
if(v == null){
Node tempNode = new Node(t.toString(),node.dist+1);
tempNode.prev = new ArrayList<Node>();
tempNode.prev.add(node);
queue.add(tempNode);
map.put(t.toString(), tempNode);
if(t.toString().equals(end)){
endNode = tempNode;
stop = true;
}
}
else {
if(v.dist == node.dist+1)
v.prev.add(node);
}
}
}
}
}
}
}
if(endNode != null){
ArrayList<String> result = new ArrayList<String>();
result.add(endNode.me);
findPath(endNode,result,start);
}
return answer;
}
}

【leetcode刷题笔记】Word Ladder II的更多相关文章

  1. 【leetcode刷题笔记】Permutations II

    Given a collection of numbers that might contain duplicates, return all possible unique permutations ...

  2. 【leetcode刷题笔记】Subsets II

    Given a collection of integers that might contain duplicates, S, return all possible subsets. Note: ...

  3. 【leetcode刷题笔记】N-Queens II

    Follow up for N-Queens problem. Now, instead outputting board configurations, return the total numbe ...

  4. LeetCode刷题笔记和想法(C++)

    主要用于记录在LeetCode刷题的过程中学习到的一些思想和自己的想法,希望通过leetcode提升自己的编程素养 :p 高效leetcode刷题小诀窍(这只是目前对我自己而言的小方法,之后会根据自己 ...

  5. LeetCode刷题笔记 - 12. 整数转罗马数字

    学好算法很重要,然后要学好算法,大量的练习是必不可少的,LeetCode是我经常去的一个刷题网站,上面的题目非常详细,各个标签的题目都有,可以整体练习,本公众号后续会带大家做一做上面的算法题. 官方链 ...

  6. 18.9.10 LeetCode刷题笔记

    本人算法还是比较菜的,因此大部分在刷基础题,高手勿喷 选择Python进行刷题,因为坑少,所以不太想用CPP: 1.买股票的最佳时期2 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格. ...

  7. Leetcode刷题笔记(双指针)

    1.何为双指针 双指针主要用来遍历数组,两个指针指向不同的元素,从而协同完成任务.我们也可以类比这个概念,推广到多个数组的多个指针. 若两个指针指向同一数组,遍历方向相同且不会相交,可以称之为滑动窗口 ...

  8. 【leetcode刷题笔记】Length of Last Word

    Given a string s consists of upper/lower-case alphabets and empty space characters ' ', return the l ...

  9. 【leetcode刷题笔记】Palindrome Partitioning II

    Given a string s, partition s such that every substring of the partition is a palindrome. Return the ...

随机推荐

  1. Mybatis结果生成键值对

    在实际应用中我们经常会遇到这样的情况,需要给下拉框赋值,这个时候就需要键值对了,具体使用方法如下 1,在maper.xml文件中定义结果类型(resultType)定义为hashmap,如下所示 &l ...

  2. 如何创建Windows定时任务

    我们经常使用电脑,有没有那么一个瞬间想着要是电脑可以每隔一段时间,自动处理一件事情就好了呢? 其实Windows还真有这样的功能,很多软件检测更新就是通过这个方法实现的. 这次我们来做一个简易的喝水提 ...

  3. VS+mysql+EF搭建

    2016年7月6日更新: vs2010只需要安装mysql的.net connector就可以 vs2012, vs2015都需要安装.net connector + ODBC connector才行 ...

  4. ChemDraw 15出现安装异常如何处理

    化学绘图软件ChemDraw最近更新了,更新后的是2015版本,ChemDraw Professional 15是其中组件之一.一些用户朋友在使用ChemDraw 15的过程中由于对软件的不了解往往会 ...

  5. SSH总结(二)

    1.文件的操作,读写文件,解决乱码问题 读文件 InputStreamReader isr = new InputStreamReader(new FileInputStream(new File(p ...

  6. modelform 对象和model之间的关系

    一.modelform的每一个标签对象 for bound_field in form:            print('form.model',form.Meta.model)          ...

  7. CentOS6.8部署SVN

    第1章 安装svn服务 1.1 准备操作系统并查看系统环境 [root@localhost ~]# cat /etc/redhat-release CentOS release 6.8 (Final) ...

  8. I - Doing Homework again(贪心)

    I - Doing Homework again Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & ...

  9. JavaScript基础深入之

    JS的数值类型是分为两类:基本数据类型和引用数据类型. 基本类型占据的内存栈空间,引用类型被保存在堆空间.引用类型赋值的变量也是被保存在栈空间的,它的作用类似于电视遥控器,负责操作堆空间内指向的对象. ...

  10. Linux 下安装svn

    安装步骤如下: 1.yum install subversion   2.输入rpm -ql subversion查看安装位置,如下图:   我们知道svn在bin目录下生成了几个二进制文件. 输入 ...