126. Word Ladder II

Description

Given two words (beginWord and endWord), and a dictionary's word list, find all shortest transformation sequence(s) from beginWord to endWord, such that:

  1. Only one letter can be changed at a time
  2. Each transformed word must exist in the word list. Note that beginWord is not a transformed word.

For example,

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

Return

[
["hit","hot","dot","dog","cog"],
["hit","hot","lot","log","cog"]
]

Note:

  • Return an empty list if there is no such transformation sequence.
  • All words have the same length.
  • All words contain only lowercase alphabetic characters.
  • You may assume no duplicates in the word list.
  • You may assume beginWord and endWord are non-empty and are not the same.

UPDATE (2017/1/20):
The wordList parameter had been changed to a list of strings (instead of a set of strings). Please reload the code definition to get the latest changes.

Solution

BFS, time O(n ^ 2), space?

跟"Word Ladder"相同的思路,用一种类似Dijkistra的算法来做。将beginWord to currWord的所有ladder保存在map中即可。注意current level words需要在当前层全部遍历完毕之后再全部从dict中移除掉,否则只会找到一条ladder,而题目中要求找到所有最短的ladder。

class Solution {
    public List> findLadders(String beginWord, String endWord, List wordList) {
        Set dict = new HashSet<>();
        dict.addAll(wordList);
        
        Queue queue = new LinkedList<>();
        queue.offer(beginWord);
        
        Map>> word2ladders = new HashMap<>();
        List> list = new ArrayList<>();
        list.add(Arrays.asList(beginWord));
        word2ladders.put(beginWord, list);
        
        dict.remove(beginWord); // don't forget to remove beginWord from dict
        // stop loop is queue is empty or target path to endWord already found
        while (!queue.isEmpty() && !word2ladders.containsKey(endWord)) {
            Set nextLevelWords = new HashSet<>();   // store next level words
            
            while (!queue.isEmpty()) {  // traverse current level words
                String curr = queue.poll();
                char[] arr = curr.toCharArray();
                
                for (int i = 0; i < arr.length; ++i) {
                    char tmp = arr[i];
                    
                    for (char c = 'a'; c <= 'z'; ++c) {
                        if (c == tmp) {     // skip curr it self
                            continue;
                        }    
                        arr[i] = c;
                        String next = new String(arr);
                        
                        if (!dict.contains(next)) {
                            continue;
                        }
                        
                        nextLevelWords.add(next);
                        if (!word2ladders.containsKey(next)) {
                            word2ladders.put(next, new ArrayList<>());
                        }

                        for (List path : word2ladders.get(curr)) {
                            List nextPath = new ArrayList<>(path);
                            nextPath.add(next);
                            word2ladders.get(next).add(nextPath);
                        }
                    }
                    
                    arr[i] = tmp;
                }
            }
            
            dict.removeAll(nextLevelWords); // nextLevelWords should be marked as visited
            queue.addAll(nextLevelWords);   // add all nextLevelWords to the queue
        }
        
        return word2ladders.getOrDefault(endWord, Collections.EMPTY_LIST);
    }
}

你可能感兴趣的:(126. Word Ladder II)