思路一:
先用bfs遍历最短路径并记录每个节点的前序节点,后用dfs从end开始回溯到start生成所有的路径。
HashMap<String,Integer> hm=new HashMap<String,Integer>();
int[]len;
List<String>[]list;
List<List<String>>lists=new ArrayList<List<String>>();
LinkedList<String>path=new LinkedList<String>();
String start;
public List<List<String>> findLadders(String start, String end, Set<String> dict) {
this.start=start;
hm.put(start,0);
hm.put(end,1);
int length=2;
for(String word:dict){
hm.put(word,length);
length++;
}
len=new int[length];
list=new List[length];
for(int i=0;i<length;i++){
list[i]=new ArrayList<String>();
len[i]=Integer.MAX_VALUE;
}
bfs(start,end);
dfs(end);
return lists;
}
public void dfs(String v){
if(v.equals(start)){
List<String>p=new ArrayList<String>();
p.add(v);
for(int i=path.size()-1;i>=0;i--){
p.add(path.get(i));
}
lists.add(p);
return;
}
path.add(v);
for(String s:list[hm.get(v)]){
dfs(s);
}
path.removeLast();
return;
}
public void bfs(String s,String e){
Queue<String>queue=new LinkedList<String>();
queue.add(s);
len[hm.get(s)]=0;
while(!queue.isEmpty()){
String w=queue.poll();
for(String i:findAdj(w)){
if(len[hm.get(w)]+1<=len[hm.get(i)]){
list[hm.get(i)].add(w);
queue.add(i);
len[hm.get(i)]=len[hm.get(w)]+1;
}
}
}
}
结果超时了,分析下来数据量大的时候记录前序节点太费时间需要O(n^2)的时间复杂度。
思路二、
bfs的时候利用每个节点的层数记录节点的位置,在dfs生成路径的时候根据层数判断前序节点并生成路径。这样记录前序节点的时间复杂度降为O(n)。
HashMap<String,Integer>hm=new HashMap<String,Integer>();
List<List<String>>lists=new ArrayList<List<String>>();
String start;
String end;
public List<List<String>> findLadders(String start, String end, Set<String> dict){
this.start=start;
this.end=end;
bfs(dict);
dfs(end,new ArrayList<String>(),dict);
return lists;
}
public void bfs(Set<String>dict){
Queue<String>queue=new LinkedList<String>();
queue.add(start);
hm.put(start, 0);
int len=0;
while(!queue.isEmpty()){
String current=queue.poll();
for(String next:findAdj(current,dict)){
if(hm.get(current)>=len&&len!=0)continue;
if(next.equals(end))len=hm.get(current)+1;
if(!hm.containsKey(next)&&!next.equals(end))queue.add(next);
if(!hm.containsKey(next))hm.put(next,hm.get(current)+1);
}
}
}
public void dfs(String v,List<String>path,Set<String> dict){
if(v.equals(start)){
Collections.reverse(path);
lists.add(path);
return;
}
if(v.equals(end))path.add(v);
for(String next:findAdj(v,dict)){
if(hm.containsKey(next)&&hm.get(next)==hm.get(v)-1){
List<String>newPath=new ArrayList<String>(path);
newPath.add(next);
dfs(next,newPath,dict);
}
}
}
public List<String>findAdj(String s,Set<String> dict){
List<String>list=new ArrayList<String>();
for(int i=0;i<s.length();i++){
for(char j='a';j<='z';j++){
StringBuilder sb=new StringBuilder(s);
sb.setCharAt(i,j);
String str=sb.toString();
if((dict.contains(str)||start.equals(str)||end.equals(str))&&!str.equals(s))list.add(str);
}
}
return list;
}