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.

Note:

  • Return 0 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.

 

one set [visited] record visited words in last layer, one set [current] record words in the current layer, one set [dict] record words in dict(candidates for the ladder)

change each letter of the words in [visited] to see whether dict contains the new word, if yes, remove the word from dict, and add it to [current].

visited=current

if current.isEmpty(),  return 0;

class Solution {
    public int ladderLength(String beginWord, String endWord, List<String> wordList) {
        Set<String> visited=new HashSet<>();
        visited.add(beginWord);
        Set<String> dict=new HashSet<>(wordList);
        int len=1;
        while(!dict.isEmpty()){
            Set<String> current=new HashSet<>();
            for(String str:visited){
                char[] ch=str.toCharArray();
                for(int i=0;i<ch.length;i++){
                    char c=ch[i];
                    for(char l='a';l<='z';l++){
                        if(c==l) continue;
                        ch[i]=l;
                        if(endWord.equals(String.valueOf(ch))){
                            return len+1;
                        }
                        if(dict.contains(String.valueOf(ch))){
                            dict.remove(String.valueOf(ch));
                            current.add(String.valueOf(ch));
                        }
                    }
                    ch[i]=c;
                }
            }
            if(current.isEmpty()) return 0;
            visited=current;
            len++;
        }
        return 0;
    }
}

 

注意:

不要把待比对对象和dict中的每个单词依次比较是否只变了一个字母,这样当dict单词数目巨大时时间复杂度太高,会tle。应该对待比对对象的每个字母依次替换'a'-'z'来看是否有相应的单词在dict中,这样时间复杂度是(26*word.length())。需要小心的是,把每个字母换掉后还需要换回来,不要忘了换回来这个步骤。

 

改进:

two end bfs

从两端分别开始搜索,思路完全同上,只是两边向中间搜索能大大加快。分别设置两个set,一个从start开始bfs,一个从end开始,每次从layer少的那一侧开始延展,看延展一步是否能连接上另一侧,如果可以,则找到了一条最短路径。

class Solution {
    public int ladderLength(String beginWord, String endWord, List<String> wordList) {
        Set<String> start=new HashSet<>();
        Set<String> end=new HashSet<>();
        Set<String> dict=new HashSet<>(wordList);
        if(!dict.contains(endWord)) return 0;
        start.add(beginWord);
        end.add(endWord);
        dict.remove(endWord);
        int len=2;
        while(!start.isEmpty()){
            if(start.size()>end.size()){
                Set<String> temp=start;
                start=end;
                end=temp;
            }//每次出发从小的去找大的
            Set<String> current=new HashSet<>();
            for(String str:start){
                char[] chars=str.toCharArray();
                for(int i=0;i<chars.length;i++){
                    char c=chars[i];
                    for(char l='a';l<='z';l++){
                        if(chars[i]==l) continue;
                        chars[i]=l;
                        String word=new String(chars);
                        if(end.contains(word)) return len;
                        if(dict.contains(word)){
                            current.add(word);
                            dict.remove(word);
                        } 
                    }
                    chars[i]=c;
                }
            }
            start=current;
            len++;
        }
        return 0;
    }
}

注意,add一个相应的就要remove一个,这道题代码相对比较长,细节的地方容易出现笔误或者漏掉,一定要小心,理清楚逻辑再写,每一步都要想清楚,不要掉了步骤。

posted on 2018-09-25 10:31  elsie12  阅读(94)  评论(0)    收藏  举报