LeetCode127. Word Ladder

Given two words (beginWord and endWord), and a dictionary's word list, find the length of shortest transformation sequence 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"]
 
As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog",
return its length 5.
 
 

 
一刷:
思路:非常妙的一个题。开始并没有想到要用图的BFS,但是题目的暗示:求最短变换路径的长度,其实就可以转换成求图的最短路径长度。可以将每个单词视为一个节点,然后如果可以相互转换的则认为在图中是相连的。
 
用bfs解决最短路径有三个关键点:
  • 如何找到当前点的相邻点:方法一是直接从集合里搜,时间复杂度是n*w,n是集合中单词个数,w是每个单词的长度,当集合里有成千上万个单词时这显然不是一种好方法;方法二是将当前单词的每个字母都用a-z中的字母代替,看集合中有没有代替后的这个单词,如果有则加入相邻点的list。
  • 如何判重:即访问过的点不能再访问了。
  • 找到节点后如何backtracking找到经过的路径。
 public int ladderLength(String beginWord, String endWord, List<String> wordList) {
        HashSet<String> dict=new HashSet<String>();
        if(wordList.size()==0 || wordList==null){
            return 0;
        }
        for(String s:wordList){
            dict.add(s);
        }
        HashSet<String> visited=new HashSet<String>();
        Queue<String> queue=new LinkedList<String>();

        if(beginWord.equals(endWord)){
            return 1;
        }
        int pathLength=1;

        queue.add(beginWord);
        visited.add(beginWord);

        while(!queue.isEmpty()){
            int size=queue.size();
            pathLength++;
            for(int i=0;i<size;i++){
                String word=queue.poll();
                for(String nextWord:getNextWord(word,dict)){
                   if(!visited.contains(nextWord)){
                       if(nextWord.equals(endWord)){
                           return pathLength;
                       }
                       visited.add(nextWord);
                       queue.add(nextWord);
                   }
               }
            }

        }
        return 0;
    }
    private List<String> getNextWord(String word,HashSet<String> dict){
        List<String> ret=new ArrayList<String>();
        for(char c='a';c<='z';c++){
            for(int i=0;i<word.length();i++){
                if(c==word.charAt(i)){
                    continue;
                }
                String nextWord=wordReplace(word,i,c);
                if(dict.contains(nextWord)){
                    ret.add(nextWord);
                }
            }
        }
        return ret;
    }
    private String wordReplace(String word,int index,char c){
        char[] newWord=word.toCharArray();
        newWord[index]=c;
        return new String(newWord);
    }
View Code

二刷:

之前的单向BFS已经超时了,于是参考了双向BFS解法

双向BFS,复杂度更低,思想就是两个SET, 交替扩展,直到两个set有元素重合,即有一条可通路

/**
 * 双向BFS,复杂度更低,思想就是两个SET, 交替扩展,直到两个set有元素重合,即有一条可通路
 */

public class WordLadder {

    public int ladderLength(String beginWord, String endWord, List<String> wordList) {
        int step = 0;
        Set<String> s1 = new HashSet<>();
        Set<String> s2 = new HashSet<>();
        Set<String> dict = new HashSet<>();
        if (!wordList.contains(endWord)) return step;
        for (String word : wordList) dict.add(word);
        s1.add(beginWord);
        s2.add(endWord);
        while (!s1.isEmpty() && !s2.isEmpty()) {
            step++;
            if (s1.size() > s2.size()) swap(s1, s2); //每次都扩展容量小的那个set
            Set<String> tmpSet = new HashSet<>();
            for (String word : s1) {
                for (String newWord : getNextWord(word)) {
                    if (s2.contains(newWord)) return step + 1;
                    if (!dict.contains(newWord)) continue;
                    dict.remove(newWord);
                    tmpSet.add(newWord);
                }
            }
            s1 = tmpSet;
        }
        return 0;
    }

    private List<String> getNextWord(String word) {
        List<String> res = new ArrayList<>();
        res.add(word);
        for (int i = 0; i < word.length(); i++) {
            for (char c = 'a'; c <= 'z'; c++) {
                String newWord = replaceWord(word, i, c);
                res.add(newWord);
            }
        }
        return res;
    }

    private void swap(Object o1, Object o2) {
        Object tmp = o1;
        o1 = o2;
        o2 = tmp;
    }

    private String replaceWord(String word, int index, char c) {
        char[] newWord = word.toCharArray();
        newWord[index] = c;
        return new String(newWord);
    }

    public static void main(String[] args) {
        WordLadder wordLadder = new WordLadder();
        String[] strings = {"hot","dog"};
        System.out.println(wordLadder.ladderLength("hot", "dog", Arrays.asList(strings)));
    }
}
View Code
扫描二维码关注公众号,回复: 1737518 查看本文章

猜你喜欢

转载自www.cnblogs.com/shawshawwan/p/9221096.html