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. 【Mac + ATX基于uiautomator2】使用weditor时,报错:requests.exceptions.ConnectionError: ('Connection aborted.', ConnectionResetError(54, 'Connection reset by peer'))

    产生以下原因找到了:是因为启动了appium,两者冲突,不能同时使用. 之前讲过怎么安装u2([Mac安装,ATX基于uiautomator2]之安装步骤)以及使用weditor, 但是经过一段时间, ...

  2. php 字符串截取

    $str="3,22,11,444,33,1,3455,33,22,444,55,66,77,88,99,554336,"; echo substr($str,0,strlen($ ...

  3. Photoshop脚本之jpg转换成eps

    function saveEPS( doc, saveFile ) { var saveOptions = new EPSSaveOptions( ); saveOptions.encoding = ...

  4. Java类载入器原理分析

    一:Java虚拟机中能够安装多个类载入器,系统默认是三个基本的类载入器: Bootstrap  ExtClassLoader  AppClassLoader 类载入器也是Java类.由于其它Java类 ...

  5. Unity3D学习笔记——NGUI之UIInput

    UIInput:这个组件可以用于创建输入框和编辑文本. 效果图如下: 一:使用步骤 1.首先创建一个背景,可以用Sprite也可以是Widget. 我这里使用的是空白的Widget 2.为其添加一个L ...

  6. centos7 更换yum源为阿里云

    mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup curl -o /etc/yum.repos ...

  7. python3----函数(join)

    今天写python 100例时,有个题目是大致是这样的:已知输入形式是1+3+2+1,要求输出形式为1+1+2+3 一开始思路是将输入的字符串用split()函数划分成数组,在对数组进行排序,再用fo ...

  8. 三个内置模块shutil logging hashlib config

    高级的 文件.文件夹.压缩包 处理模块 shutil.copyfileobj(fsrc, fdst[, length])将文件内容拷贝到另一个文件中 1 import shutil 2 3 shuti ...

  9. Golang中的正则表达式

    声明:文章转自GoLove 用法: 单一: . 匹配任意一个字符,如果设置 s = true,则可以匹配换行符 [字符类] 匹配"字符类"中的一个字符,"字符类" ...

  10. 关于java后台如何接收xml格式的数据

    业务场景:用户发送下单请求,格式为xml格式,服务器接收数据完成下单,并返回结果给客户. 请求格式: <request> <head> <sign></sig ...