问题重述:
Given two words (beginWord and endWord), and a dictionary’s word list, find the length of shortest transformation sequence from beginWord to endWord, such that:
Only one letter can be changed at a time Each intermediate word must exist in the word list
For example,
Given:
beginWord = “hit”
endWord = “cog”
wordList = [“hot”,”dot”,”dog”,”lot”,”log”]
As one shortest transformation is “hit” -> “hot” -> “dot” -> “dog” -> “cog”,
return its length 5.
Note:
Return 0 if there is no such transformation sequence.
All words have the same length.
All words contain only lowercase alphabetic characters.
Subscribe to see which companies asked this question
代码如下:其实代码啦,思想啦都是那位大神的,他在LeetCode上给过源码啦,我只是说一下我对他算法的理解
import java.util.HashSet;
import java.util.Set;
import org.junit.Test;
/**
* 基本思想:模拟
*/
public class Solution {
public int ladderLength(String beginWord, String endWord, Set<String> wordList) {
Set<String> start = new HashSet<>();
Set<String> end = new HashSet<>();
start.add(beginWord);
end.add(endWord);
return solve(start, end, wordList, 1);
}
public int solve(Set<String> start,Set<String> end,Set<String> wordList,int step){
if(start.isEmpty()){
return 0;
}
if(start.size()>end.size()){
return solve(end,start,wordList,step);
}
wordList.removeAll(start);
Set<String> next = new HashSet<String>();
for(String s : start){
char[] chs = s.toCharArray();
for (int i = 0; i < chs.length; i++) {
for (int j = 'a'; j <='z'; j++) {
char t = chs[i];
chs[i]=(char) j;
String temp = new String(chs);
if(end.contains(temp)){
return step+1;
}
if(wordList.contains(temp)){
next.add(temp);
}
chs[i] = t;
}
}
}
return solve(next, end, wordList, step+1);
}
@Test
public void test(){
Set<String> set = new HashSet<>();
set.add("hot");
set.add("dog");
set.add("dot");
ladderLength("hot","dog",set);
}
}
创建两个集合,一个开始集合、一个结束集合,由开始集合向结束集合靠近,或者由结束集合向开始集合靠近,这个想法有点像图论中求点到点最短路的算法,都是集合向集合逼近,只不过这个算法有点盲目基本是靠穷举举出来的。
for(String s : start){
char[] chs = s.toCharArray();
for (int i = 0; i < chs.length; i++) {
for (int j = 'a'; j <='z'; j++) {
char t = chs[i];
chs[i]=(char) j;
String temp = new String(chs);
if(end.contains(temp)){
return step+1;
}
if(wordList.contains(temp)){
next.add(temp);
}
chs[i] = t;
}
}
}
这段代码就是穷举的代码,将开始字符集中的每一个字符串中的每一个字符都替换一次,然后判断结果集合或者字符集合里是否包含更改后的字符,如果包含,添加到next集合中,next集合是下一次要查询的开始集。
需要注意的是,更改字符后记得把更改后的字符改回来(就像搜索算法中的染色,有些染色必须再染回去,不然会发生错误,我算法敲得少,所以经常忘记这一点)
此外原作者进行了一个简化:
wordList.removeAll(start);
将查询过的字符串从字符表中删除,这一步确保算法不做重复的工作,极大得改进了算法性能
还有一个优化就是:
if(start.size()>end.size()){
return solve(end,start,wordList,step);
}
这一步确保三重循环是循环的较小的那个集合,可以带来一定的优化