DAG bfs + dfs 126,

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
  • beginWordendWord, 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;
    }
}

 

posted @ 2024-11-24 05:10  xiaoyongyong  阅读(6)  评论(0编辑  收藏  举报