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 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.
最近做完题习惯看看discuss,发现了别的速度快的方法。
public class Solution {
boolean able_reach(String str1, String str2){
int diff = 0;
int i,len = str1.length();
for(i = 0; i < len; ++ i){
if(str1.charAt(i) != str2.charAt(i)){
++diff;
}
}
return diff==1;
}
List<Integer>[] BuildGraph(String beginWord, String endWord, Set<String> wordList, String[] hp){
ArrayList<Integer>[] graph = new ArrayList[wordList.size()+2];
int idx = 0;
//establish relationship between idx and string
hp[idx] = beginWord;
for(String str:wordList){
++idx;
hp[idx] = str;
}
++idx;
hp[idx] = endWord;
//build map
int idx1,idx2;
for(int i = 0; i < graph.length; ++i){
graph[i] = new ArrayList<Integer>();
}
for(idx1 = 0; idx1 < graph.length; ++idx1){
for(idx2 = idx1 + 1; idx2 < graph.length; ++idx2){
if (able_reach(hp[idx1],hp[idx2])){
graph[idx1].add(idx2);
graph[idx2].add(idx1);
}
}
}
return graph;
}
List<List<String>> print_paths(ArrayList<Integer>[] pre, String[] word_map, List<List<String>> paths){
ArrayList<String> path = new ArrayList<String>();
path.add(word_map[word_map.length - 1]);
print_path(pre,word_map.length-1,path,paths,word_map);
return paths;
}
void print_path(ArrayList<Integer>[] pre,int node,ArrayList<String> path, List<List<String>> paths, String[] word_map){
if(node == 0){
ArrayList<String> temp_path = new ArrayList<String>();
temp_path.addAll(path);
paths.add(temp_path);
return;
}
for(int pre_node:pre[node]){
path.add(word_map[pre_node]);
print_path(pre,pre_node,path,paths,word_map);
path.remove(path.size()-1);
}
return;
}
public List<List<String>> findLadders(String beginWord, String endWord, Set<String> wordList) {
String[] word_map = new String[wordList.size()+2];
List<Integer>[] graph = BuildGraph(beginWord, endWord, wordList, word_map);
//dijkstra
int i,j,distance;
int[] visited = new int[graph.length];
int min_distance;
int[] dis = new int[graph.length];
ArrayList<Integer>[] pre = new ArrayList[graph.length+2];
for(i = 0; i < pre.length; ++i){
pre[i] = new ArrayList<Integer>();
}
//initialize dis[]
Iterator graph_it = graph[0].iterator();
while(graph_it.hasNext()){
dis[(int) graph_it.next()] = 1;
}
for(i = 1; i < graph.length; ++i){
if(dis[i] != 1){
dis[i] = graph.length;
}
}
i = 0;
while(i < graph.length){
int node;
min_distance = graph.length;
for(node = 0; node < graph.length; ++ node){
if(visited[node] == 0 && dis[node] < min_distance){
min_distance = dis[node];
}
}
for(node = 0; node < graph.length; ++node){
if(visited[node] == 0 && dis[node] == min_distance){
visited[node] = 1;
++i;
for(Integer next_node:graph[node]){
int temp_dis = 1 + dis[node];
if(visited[next_node] == 0 && temp_dis <= dis[next_node]){
pre[next_node].add(node);
dis[next_node] = temp_dis;
}
}
}
}
}
List<List<String>> temp_paths = new ArrayList<List<String>>();
print_paths(pre,word_map,temp_paths);
Iterator it = temp_paths.iterator();
List<List<String>> paths = new ArrayList<List<String>>();
while(it.hasNext()){
List<String> temp_path = (List<String>) it.next();
String[] for_path = new String[temp_path.size()];
int temp_node = temp_path.size() - 1;
for(String node:temp_path){
for_path[temp_node] = node;
--temp_node;
}
List<String> path = new ArrayList<String>();
for(String node:for_path){
path.add(node);
}
paths.add(path);
}
return paths;
}
}