首页 技术 正文
技术 2022年11月11日
0 收藏 651 点赞 3,720 浏览 2528 个字

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记录这个到达这个节点的所有最短路径上的前驱结点。举个例子:

[Leetcode][JAVA] Word Ladder II

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);
}
}
相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,497
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,910
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,744
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,498
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:8,136
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:5,300