最短单词路径
给定两个单词(beginWord 和 endWord)和一个字典,找到从 beginWord到 endWord 的最短转换序列的长度。转换需遵循如下规则:
- 每次转换只能改变一个字母。
- 转换过程中的中间单词必须是字典中的单词。
说明:
- 如果不存在这样的转换序列,返回 0。
- 所有单词具有相同的长度。
- 所有单词只由小写字母组成。
- 字典中不存在重复的单词。
- 你可以假设 beginWord 和 endWord 是非空的,且二者不相同。
class Solution {
/*
/*
把beginword添加到字典中;从字典中首先查找将beginword改变一个字符的满足条件的单词;第一层节点;
其次,顺着每一个节点再次查找下去,首先遍历到的满足endword的节点路径就是我们要找的最短路径
这是一个广度优先搜索的问题
难点:如何构建满足条件的查找范围--图;
如何判断一个字符是否经过一次改变就满足条件;
*/
//1.总的函数
public int ladderLength(String beginWord, String endWord, List<String> wordList) {
wordList.add(beginWord);
int N=wordList.size();
int start=N-1;
int end=0;
//先在字典中找到endWord的坐标
while(end<0 && !wordList.get(end).equals(endWord)){
end++;
}
//没有找到
if(end==N){
return 0;
}
//构件图--搜索路径
List<Integer>[] graphic = buildGraphic(wordList);
return getShortestPath(graphic, start, end);
}
//2.构件图---用索引来表示字符是否满足条件
private List<Integer>[] buildGraphic(List<String> wordList){
int N=wordList.size();
List<Integer>[] graphic=new List[N];
for(int i=0;i<N;i++ ){
graphic[i]=new ArrayList<>();
for(int j=0;j<N;j++){
//如果满足之改变一个字符就相等的条件
if(isConnect(wordList.get(i),wordList.get(j))){
graphic[i].add(j);
}
}
}
return graphic;
}
private boolean isConnect(String s,String t){
int diffcnt=0;
int N=s.length();
for(int i=0;i<N && diffcnt<=1;i++){
if(s.charAt(i)!=t.charAt(i)){
diffcnt++;
}
}
return diffcnt==1;
}
private int getShortestPath(List<Integer>[] graphic, int start, int end){
Queue<Integer> queue=new LinkedList<>();
int path=1;
queue.add(start);
boolean[] marked=new boolean[graphic.length];
marked[start]=true;
while(!queue.isEmpty()){
int size=queue.size();
path++;
while(size-- > 0){
int cur=queue.poll();
for(int next:graphic[cur]){
if(next==end){
return path;
}
if(marked[next]){
continue;
}
marked[next]=true;
queue.add(next);
}
}
}
return 0;
}
}