Given two words (beginWord and endWord), and a dictionary's word list, find all shortest transformation sequence(s) from beginWord toendWord, such that:
- Only one letter can be changed at a time
- Each transformed word must exist in the word list. Note that beginWord is not a transformed word.
For example,
Given:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log","cog"]
Return
[
["hit","hot","dot","dog","cog"],
["hit","hot","lot","log","cog"]
]
Note:
- Return an empty list if there is no such transformation sequence.
- All words have the same length.
- All words contain only lowercase alphabetic characters.
- You may assume no duplicates in the word list.
- You may assume beginWord and endWord are non-empty and are not the same.
这道题是LeetCode最难的之一了,刚开始直接做这个没做Word Ladder,感觉还是过于复杂搞不定。于是先回去做127 Word Ladder,用广度优先搜索得到最短的转换次数(详见127word Ladder)。
在此基础上,很容易将返回层数改造成返回每一层搜索到的字符串List,得到每一层的List之后还是可以先做剪枝,因为得到的是从前往后的每个相邻层之间的转换,可以利用从后往前搜索,排除不能到达的字符串。
例如题目中的例子每层就得到:
hit
hot
dot,lot
dog,log
cog
最后逐层构造转换List即可。看到其他博客说最后构造用的dfs,这里我用的bfs,感觉更直观
AC代码,372 ms,还有可以优化的地方:
class Solution {
public List<List<String>> findLadders(String beginWord, String endWord,
List<String> wordList) {
if(!wordList.contains(endWord)){
return new ArrayList<List<String>>();
}
if(beginWord.equals(endWord)){
List<List<String>> list = new ArrayList<List<String>>();
List<String> strs = new ArrayList<String>();
strs.add(beginWord);
list.add(strs);
return list;
}
if(compareTwoStr(beginWord,endWord)){
List<List<String>> list = new ArrayList<List<String>>();
List<String> strs = new ArrayList<String>();
strs.add(beginWord);
strs.add(endWord);
list.add(strs);
return list;
}
if(wordList.contains(beginWord)){
wordList.remove(beginWord);
}
List<List<String>> list = new ArrayList<List<String>>();
list = ladders(beginWord,endWord,wordList);
if(list.size() == 0){
return list;
}
list = removeLadders(beginWord, endWord, wordList, list);
if(list.size() == 0){
return list;
}
List<List<String>> tempList = new ArrayList<List<String>>();
tempList.add(new ArrayList<String>());
tempList.get(0).add(beginWord);
List<List<String>> tempList2 = new ArrayList<List<String>>();
for(int i=1;i<list.size();i++){
for(String str: list.get(i)){
for(int j=0;j< tempList.size();j++){
if(compareTwoStr(str, tempList.get(j).get(tempList.get(j).size()-1))){
tempList2.add(new ArrayList<String>(tempList.get(j)));
tempList2.get(tempList2.size()-1).add(str);
}
}
}
tempList.clear();
tempList = new ArrayList<List<String>>(tempList2);
tempList2.clear();
}
return tempList;
}
public List<List<String>> ladders(String beginWord, String endWord, List<String> wordList) {
List<List<String>> list = new ArrayList<List<String>>();
list.add(new ArrayList<String>());
list.get(0).add(beginWord);
List<String> visited = new ArrayList<String>();
List<String> remain = new ArrayList<String>(wordList);
visited.add(beginWord);
int index = 0;
int visitLen = 1;
int count = 1;
while(!visited.contains(endWord)){
boolean found = false;
list.add(new ArrayList<String>());
for(int i=index;i<index+visitLen;i++){
for(int j=remain.size()-1 ;j>=0; j--){
if(compareTwoStr(remain.get(j), visited.get(i))
&& !visited.contains(remain.get(j))){
visited.add(remain.get(j));
list.get(list.size()-1).add(remain.get(j));
found = true;
remain.remove(j);
}
}
}
if(!found){
list.clear();
return list;
}
count++;
index += visitLen;
visitLen = visited.size() - index;
}
for(int i= list.get(list.size()-1).size()-1 ;i>=0;i--){
if(!list.get(list.size()-1).get(i).equals(endWord)){
list.get(list.size()-1).remove(i);
}
}
return list;
}
//辅助函数,判断两串只相差1字符
public boolean compareTwoStr(String str1,String str2){
int count = 0;
for(int i=0;i<str1.length();i++){
if(str1.charAt(i) != str2.charAt(i)){
count++;
if(count>1)
return false;
}
}
return count == 1;
}
//remove
public List<List<String>> removeLadders(String beginWord,
String endWord, List<String> wordList,List<List<String>> list) {
for(int i=list.size()-1;i>0;i--){
for(int j=list.get(i-1).size()-1;j>=0;j--){
boolean canReach = false;
for(String str2 : list.get(i)){
if(compareTwoStr(list.get(i-1).get(j), str2)){
canReach = true;
break;
}
}
if(!canReach){
list.get(i-1).remove(j);
}
}
}
return list;
}
}
LeetCode单词梯难题解
本文详细解析LeetCode上难度较高的单词梯问题,通过广度优先搜索策略寻找从开始单词到结束单词的所有最短转换路径,并附带实现代码。
638

被折叠的 条评论
为什么被折叠?



