DAG bfs + dfs 126,

xiaoyongyong發表於2024-11-24
126. Word Ladder II

A transformation sequence from word beginWord to word endWord using a dictionary wordList is a sequence of words beginWord -> s1 -> s2 -> ... -> sk such that:

  • Every adjacent pair of words differs by a single letter.
  • Every si for 1 <= i <= k is in wordList. Note that beginWord does not need to be in wordList.
  • sk == endWord

Given two words, beginWord and endWord, and a dictionary wordList, return all the shortest transformation sequences from beginWord to endWord, or an empty list if no such sequence exists. Each sequence should be returned as a list of the words [beginWord, s1, s2, ..., sk].

Example 1:

Input: beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log","cog"]
Output: [["hit","hot","dot","dog","cog"],["hit","hot","lot","log","cog"]]
Explanation: There are 2 shortest transformation sequences:
"hit" -> "hot" -> "dot" -> "dog" -> "cog"
"hit" -> "hot" -> "lot" -> "log" -> "cog"

Example 2:

Input: beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log"]
Output: []
Explanation: The endWord "cog" is not in wordList, therefore there is no valid transformation sequence.

Constraints:

  • 1 <= beginWord.length <= 5
  • endWord.length == beginWord.length
  • 1 <= wordList.length <= 500
  • wordList[i].length == beginWord.length
  • beginWord, endWord, and wordList[i] consist of lowercase English letters.
  • beginWord != endWord
  • All the words in wordList are unique.
  • The sum of all shortest transformation sequences does not exceed 105.
class Solution {
    // DAG
    private Map<String, List<String>> map = new HashMap<>();
    // 最終result
    private List<List<String>> result = new ArrayList<>();
    public List<List<String>> findLadders(String beginWord, String endWord, List<String> wordList) {
        // 放入set
        Set<String> set = new HashSet<>(wordList);
        set.remove(beginWord);

        //全域性visited
        Set<String> visited = new HashSet<>();

        // bfs建立DAG
        /**
        關鍵在於dag的建立
        1.需要一個層級list去存放這層訪問過的元素,這層結束統一從set中刪除
        2.另外透過這個list排重,如果已經入que的不要重複入
         */
        Queue<String> que = new LinkedList<>();
        que.offer(beginWord);
        set.remove(beginWord);
        while(!que.isEmpty()) {
            // 儲存當前層訪問過的元素,便於這層結束的時候統一從set刪除
            // 為什麼這麼做? 因為我們不是隻找一條最短路徑,而是要找出所有的,
            // 所以即使找到一個路徑,還需要找到與這個元素相關的其他路徑
            List<String> levelVisited = new ArrayList<>();
            int size = que.size();
            for(int i = 0; i < size; i++) {
                String curr = que.poll();
                // 遍歷所有neighbor元素
                List<String> others = getNeighbors(set, curr);
                for(String other : others) {
                    levelVisited.add(other);
                    // 將curr放入other的parent 列表
                    List<String> list = map.getOrDefault(other, new ArrayList<>());
                    list.add(curr);
                    map.put(other, list);
                    // 如果該元素還沒有入que過,那麼入que
                    if(visited.add(other)) que.offer(other);
                }
            }
            //最終將這層訪問過的元素都刪除
            for(String str : levelVisited) {
                set.remove(str);
            }
        }
        // dfs找到所有路徑
        List<String> list = new ArrayList<>();
        list.add(endWord);
        dfs(list, endWord, beginWord, new HashSet<>());

        return result;
    }
    private void dfs(List<String> currList, String currWord, String beginWord, Set<String> visited) {
        if(currWord.equals(beginWord)) {
            var temp = new ArrayList(currList);
            Collections.reverse(temp);
            result.add(temp);
            return;
        }
        for(String other : map.getOrDefault(currWord, List.of())) {
            if(visited.add(other)) {
                currList.add(other);
                dfs(currList, other, beginWord, visited);
                visited.remove(other);
                currList.remove(currList.size() - 1);
            }
        }
    }

    private List<String> getNeighbors(Set<String> set, String word) {
        List<String> list = new ArrayList<>();
        for(int i = 0; i < word.length(); i++) {
            for(int j = 0; j < 26; j++) {
                char c = (char)('a' + j);
                String temp = word.substring(0, i) + c + word.substring(i + 1);
                // 不是自己; 在word列表;
                if(!temp.equals(word) && set.contains(temp)) list.add(temp);
            }
        }
        return list;
    }
}

相關文章