leetcode 126. Word Ladder II

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.

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.

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"]
]

Example 2:

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

Output: []

Explanation: The endWord "cog" is not in wordList, therefore no possible transformation.



思路:BFS,注意保存BFS过程中的信息。

        1.定义一个HashMap<String,List<String>> route 保存路径。(方向为value到key)

        2.广搜每一次循环搜一层,所以代码中不用记录String和层数的映射了。

        3.最后用DFS,在HashMap<String,List<String>> route 搜索路径。

        4.定义mark标记已搜到的单词,在下一层不会再搜到,mark[i]==0表示还未搜到,mark[i]==1表示已搜到,但还在当前  层。mark[i]==2表示搜到,并已经到了下一层,已不会搜到。

        5.因为第一版本的BFS时是遍历wordList中每个元素,再每个字符串相匹配,这样速度慢,每次匹配一个元素要O(L*m)的复杂度,L为字符串长度,m为wordList的字符串个数,AC后要600+ms。所以在第二版本中先把wordList存在一个HashMap中,在替换每个要匹配的String中的一个字符,再到HashMap中找,理论上每次匹配时间复杂度为O(26*L),AC后218ms。

第一版本:

    public List<List<String>> findLadders(String beginWord, String endWord, List<String> wordList) {
        HashMap<String,List<String>> route=new HashMap<>();//list to string
        LinkedList<String> queue=new LinkedList<>();
        List<List<String>> list=new ArrayList<>();
        int[] mark=new int[wordList.size()];
        boolean isEnd=false;//标记已找到
        queue.add(beginWord);
        while(!isEnd&&queue.size()!=0){
            int len=queue.size();
            while((len--)>0){
                String str=queue.poll();
                for(int i=0;i<wordList.size();i++){
                    if(mark[i]!=2&&connect(wordList.get(i),str)){
                        if(route.get(wordList.get(i))==null){
                            List<String> l=new ArrayList<>();
                            l.add(str);
                            route.put(wordList.get(i),l);
                        }else{
                           route.get(wordList.get(i)).add(str); 
                        }
                        if(endWord.equals(wordList.get(i))){
                            isEnd=true;//找到就是最后一次循环
                        }else{
                            if(mark[i]!=1){//本次循环已经找到次数
                                queue.add(wordList.get(i));
                            }
                        }
                        mark[i]=1;
                    }
                }
            } 
            for(int i=0;i<mark.length;i++){
                if(mark[i]==1){
                    mark[i]=2;
                }    
            }
        }
        List<String> l=new ArrayList<>();
        if(route.get(endWord)==null) return list;
        l.add(endWord);
        addString(route,list,l,endWord,beginWord);
        return list;
    }
    public void addString(HashMap<String,List<String>> route,List<List<String>> list,List<String> l,String word,String start){
        if(start.equals(word)){
            list.add(new ArrayList(l));
            return;
        }
        for(String s:route.get(word)){
            l.add(0,s);
            addString(route,list,l,s,start);
            l.remove(0);
        }
    }
    public boolean connect(String str1,String str2){
        if(str1.equals(str2)||str1.length()!=str2.length()) return false;
        int count=0;
        for(int i=0;i<str1.length();i++){
            if(str1.charAt(i)!=str2.charAt(i)){
                count++;
                if(count>1){
                    return false;
                }
            }    
        }
        return true;
    }

第二版本:

    public List<List<String>> findLadders(String beginWord, String endWord, List<String> wordList) {
        HashMap<String,List<String>> route=new HashMap<>();//list to string
        LinkedList<String> queue=new LinkedList<>();
        List<List<String>> list=new ArrayList<>();
        HashMap<String,Integer> map=new HashMap<>();//记录字符串和下标映射
        for(int i=0;i<wordList.size();i++){
            map.put(wordList.get(i),i);            
        }
        int[] mark=new int[wordList.size()];
        boolean isEnd=false;//标记已找到
        queue.add(beginWord);
        while(!isEnd&&queue.size()!=0){
            int len=queue.size();
            while((len--)>0){
                String str=queue.poll();
                for(int i=0;i<str.length();i++){
                    for(char c='a';c<='z';c++){
                        if(str.charAt(i)!=c){
                            StringBuilder sb=new StringBuilder(str);
                            sb.setCharAt(i,c);
                            if(map.get(sb.toString())!=null){//在dict中找到了string
                                int index=map.get(sb.toString());
                                if(mark[index]==2){
                                    continue;
                                }
                                if(route.get(sb.toString())==null){//路径str到sb.toString()
                                    List<String> l=new ArrayList<>();
                                    l.add(str);
                                    route.put(sb.toString(),l);//key存下一个
                                }else{
                                    route.get(sb.toString()).add(str); 
                                }
                                if(endWord.equals(sb.toString())){
                                    isEnd=true;//找到就是最后一次循环
                                }else{
                                    if(mark[index]!=1){//本次循环已经找到次数
                                        queue.add(sb.toString());
                                    }
                                }
                                mark[index]=1; 
                            }
                        }
                    }
                }
            } 
            for(int i=0;i<mark.length;i++){
                if(mark[i]==1){
                    mark[i]=2;
                }    
            }
        }       
        List<String> l=new ArrayList<>();
        if(route.get(endWord)==null) return list;
        l.add(endWord);
        addString(route,list,l,endWord,beginWord);
        return list;
    }
    public void addString(HashMap<String,List<String>> route,List<List<String>> list,List<String> l,String word,String start){
        if(start.equals(word)){
            list.add(new ArrayList(l));
            return;
        }
        for(String s:route.get(word)){
            l.add(0,s);
            addString(route,list,l,s,start);
            l.remove(0);
        }
    }
}

猜你喜欢

转载自blog.csdn.net/yaoct/article/details/80531878