leetcode126--單詞接龍II

題目鏈接:https://leetcode-cn.com/problems/word-ladder-ii/

題目描述:

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


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


說明:


    如果不存在這樣的轉換序列,返回一個空列表。
    所有單詞具有相同的長度。
    所有單詞只由小寫字母組成。
    字典中不存在重複的單詞。
    你可以假設 beginWord 和 endWord 是非空的,且二者不相同。


示例 1:

輸入:
beginWord = "hit",
endWord = "cog",
wordList = ["hot","dot","dog","lot","log","cog"]

輸出:
[
  ["hit","hot","dot","dog","cog"],
  ["hit","hot","lot","log","cog"]
]


示例 2:

輸入:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log"]

輸出: []

解釋: endWord "cog" 不在字典中,所以不存在符合要求的轉換序列。

題目分析:從一個單詞轉換到另一個單詞經過的路徑,由於中間經過轉換的路徑一定要在給定的wordlist中,並且每次變換隻能更改一個單詞,因此,我們可以把每個單詞能夠變換到的詞,也可以理解爲能達到的路徑標記出來,題目又是要求最短路徑,使用BFS可以求得,將每個單詞理解爲一個點,每個單詞能變換的過程理解爲路徑,那麼題目就轉化爲求在一個圖中從一個點到另一個點的最短路徑,綜上,先建圖,然後BFS遍歷,由於要記錄路徑所經過的節點,我們藉助map來存儲單詞的映射關係,方便輸出

class Solution {
  HashMap<String,Integer> wordmap;//爲每個單詞生成ID,簡化處理
  ArrayList<String> words ;//爲了記錄路徑,用ID來獲取單詞
  ArrayList<Integer>[] edges;//邊
  //判斷2個單詞能否相互轉化
  public boolean isOk(String s1,String s2){
     int cnt = 0;
     for(int i = 0;i < s1.length();i++){
          if(s1.charAt(i)!=s2.charAt(i))
            cnt++;
     }
     return cnt == 1;
  }
  public List<List<String>> findLadders(String beginWord, String endWord, List<String> wordList) {
       wordmap = new HashMap<>();
       words = new ArrayList<>();
       int id = 0;
       for (String str : wordList) {//建立映射
          if(!wordmap.containsKey(str)){
            wordmap.put(str, id++);
            words.add(str);
          }
       }
       //不符合要求的情況
       if(!wordmap.containsKey(endWord)) return new ArrayList<>();
       if(!wordmap.containsKey(beginWord)){//將所有單詞都建立映射
         wordmap.put(beginWord, id++);
         words.add(beginWord);
       }
        edges = new ArrayList[words.size()];
        for (int i = 0; i < words.size(); i++) {
            edges[i] = new ArrayList<>();
        }
        //建圖
       for (int i = 0; i < words.size(); i++) {
         for (int j = i+1; j < words.size(); j++) {
            if(isOk(words.get(i), words.get(j))){//可以相互轉化建立邊
                 edges[i].add(j);
                 edges[j].add(i);
            }
         }
       }
       //cost數組代表beginWord到i爲止所花費的轉換代價(次數)
       int[] cost = new int[words.size()];
       Arrays.fill(cost, 1<<20);
       List<List<String>> res = new ArrayList<>();
       int des = wordmap.get(endWord);
       //初始化
       LinkedList<ArrayList<Integer>> q = new LinkedList<>();
       ArrayList<Integer> te = new ArrayList<>();
       te.add(wordmap.get(beginWord));
       q.add(te);
       cost[wordmap.get(beginWord)] = 0;
       //BFS求最短路徑
       while(!q.isEmpty()){
         ArrayList<Integer> cur = q.poll();
         int to = cur.get(cur.size()-1);//路徑的最後一個節點
         if(to == des){//達到了終點,加入res
           ArrayList<String> temp = new ArrayList<>();
           for (Integer index : cur) {
                 temp.add(words.get(index));
           }
           res.add(temp);
         }else{//繼續遍歷下一個可達的點
            for (int i = 0; i < edges[to].size(); i++) {
               int end = edges[to].get(i);
               if(cost[end]>=cost[to]+1){//如果代價更小,就加入路徑,=代表可以相同長度的也是滿足的
                 cost[end] = cost[to]+1;//更新代價
                 ArrayList<Integer> temp = new ArrayList<>(cur);
                  temp.add(end);
                  q.add(temp);
               }
            }
         }
       }
       return res;
  }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章