1. 程式人生 > >最短單詞路徑

最短單詞路徑

 最短單詞路徑

給定兩個單詞(beginWord 和 endWord)和一個字典,找到從 beginWord到 endWord 的最短轉換序列的長度。轉換需遵循如下規則:

  1. 每次轉換隻能改變一個字母。
  2. 轉換過程中的中間單詞必須是字典中的單詞。

說明:

  • 如果不存在這樣的轉換序列,返回 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;
    }
    
}