leetcode 126. Word Ladder II ----- java

时间:2021-06-27 09:23:59

Given two words (beginWord and endWord), and a dictionary's word list, find all shortest transformation sequence(s) from beginWord to endWord, such that:

  1. Only one letter can be changed at a time
  2. Each intermediate word must exist in the word list

For example,

Given:
beginWord = "hit"
endWord = "cog"
wordList = ["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.

从start变换到end,途中只能经过字典中的单词,每次只允许差一个字母。
要求输出所有最短变换路径。

这里刚开始使用了最普通的方法,即利用DFS,超时了。

public class Solution {

    List list = new ArrayList<List>();
int num = 0;
String[] words;
String[] ans;
public List<List<String>> findLadders(String beginWord, String endWord, Set<String> wordList) { if( beginWord.length() == 0 || wordList.size() == 0 )
return list;
int len = wordList.size();
words = new String[len];
int i = 0;
for( String str : wordList ){
words[i] = str;
i++;
}
ans = new String[len+2];
ans[0] = beginWord; helper(beginWord,endWord,1);
return list; } public void helper(String beginWord,String endWord,int pos){ if( OneDiff(beginWord,endWord)){
if( num == 0 )
num = pos;
else if( num < pos )
return;
else if( num > pos ){
list.clear();
num = pos;
}
List ll = new ArrayList<String>();
for( int i = 0;i<pos;i++)
ll.add(ans[i]);
ll.add(endWord);
list.add(ll);
return ;
} for( int i = 0;i<words.length;i++){
String str = words[i];
if( str == "-1")
continue;
if( OneDiff(beginWord,str) ){
ans[pos] = str;
words[i] = "-1";
helper(str,endWord,pos+1);
words[i] = str;
}
} } public boolean OneDiff(String word1,String word2){
int flag = 0;
for( int i = 0;i<word1.length();i++){ if( word1.charAt(i) == word2.charAt(i) )
continue;
else{
if( flag == 0)
flag =1;
else
return false;
} }
return true;
}
}
}

2、使用BFS,仍旧超时了。

public class Solution {

    List list = new ArrayList<List>();
Queue queue;
HashMap map = new HashMap<String,Integer>(); public List<List<String>> findLadders(String beginWord, String endWord, Set<String> wordList) { if( beginWord.length() == 0 || wordList.size() == 0 )
return list;
queue = new LinkedList<ArrayList<String>>();
if( OneDiff(beginWord,endWord) ){
List ll = new ArrayList<String>();
ll.add(beginWord);
ll.add(endWord);
list.add(ll);
return list;
}
List ll = new ArrayList<String>();
ll.add(beginWord);
int flag = 0;
int deep = 0;
map.put(beginWord,deep);
queue.add(ll);
while( !queue.isEmpty() ){
deep++;
int len = queue.size();
for( int i = 0;i<len;i++) {
List l1 = (List) queue.poll();
String s1 = (String) l1.get(l1.size() - 1);
for (String str : wordList) {
if (OneDiff(s1, str) && ( !map.containsKey(str) || (int)map.get(str) == deep) ) {
map.put(str,deep);
List l2 = new ArrayList<String>();
l2.addAll(l1);
l2.add(str);
queue.add(l2);
if (OneDiff(str, endWord)) {
l2.add(endWord);
// for (int ii = 0; ii < l2.size(); ii++)
// System.out.print(l2.get(ii) + " ");
// System.out.println();
list.add(l2);
flag = 1;
}
}
}
}
if( flag == 1)
queue.clear();
}
return list; }
public boolean OneDiff(String word1,String word2){
int flag = 0;
for( int i = 0;i<word1.length();i++){ if( word1.charAt(i) == word2.charAt(i) )
continue;
else{
if( flag == 0)
flag++;
else
return false;
} }
if( flag == 1)
return true;
else
return false;
}
}

3、借鉴了他人的答案

优化方法:先BFS生成找到end时的生成树,标记出每个单词所在的层数。然后从目标用DFS往回找,过了大数据。

NOTE:我在代码中刚开始由于存在static,导致测试用例一直无法通过。

public class Solution {

    List list = new ArrayList<List>();
HashMap map = new HashMap<String,Integer>(); public List<List<String>> findLadders(String beginWord, String endWord, Set<String> wordList) { if( beginWord == null || beginWord.length() == 0 || wordList.size() == 0 || beginWord.length() != endWord.length() )
return list; BFS(beginWord,endWord,wordList);
if( map.size()== 1 )
return list;
DFS(endWord,beginWord,new ArrayList<String>()); return list; }
public void DFS(String beginWord,String endWord,List ans){ if( beginWord.equals(endWord) ){
ans.add(beginWord);
Collections.reverse(ans);
list.add(ans);
return ;
}
if( map.get(beginWord) == null )
return ;
ans.add(beginWord);
int deep = (int) map.get(beginWord)-1;
for( int i = 0;i<beginWord.length();i++){
char[] word = beginWord.toCharArray();
for( char ch = 'a';ch<='z';ch++) {
word[i] = ch;
String nWord = new String(word);
if ( map.get(nWord) != null && ((int) map.get(nWord) == deep)) {
ArrayList ll = new ArrayList<String>(ans);
DFS(nWord, endWord, ll); }
}
}
}
public void BFS(String beginWord,String endWord,Set<String> wordList){ Queue queue = new LinkedList<String>();
queue.add(beginWord);
map.put(beginWord,0);
while( !queue.isEmpty() ){
String str = (String) queue.poll();
if( str.equals(endWord) )
continue;
for( int i = 0 ;i <beginWord.length();i++){
char[] word = str.toCharArray();
for( char ch = 'a';ch<='z';ch++) {
word[i] = ch;
String Nword = new String(word);
if ( Nword.equals(endWord) || wordList.contains(Nword)) {
if (!map.containsKey(Nword)) {
map.put(Nword, (int) map.get(str) + 1);
queue.add(Nword);
}
}
}
}
}
} }