Word Ladder II

来源:互联网 发布:cg软件作用 编辑:程序博客网 时间:2024/06/04 19:00
Problem:

Given two words (start and end), and a dictionary, find all shortest transformation sequence(s) from start to end, such that:

  1. Only one letter can be changed at a time
  2. Each intermediate word must exist in the dictionary

For example,

Given:
start = "hit"
end = "cog"
dict = ["hot","dot","dog","lot","log"]

Return

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


Note:

  • All words have the same length.
  • All words contain only lowercase alphabetic characters.

这道题费尽周折,总是TLE,Solution1是最先提交的独立思考出来的版本。TLE的原因是维护了一个当前搜索节点的最短路径链表,而这些中间路径大部分都不会出现在最终结果中。而且,对于路径A->B->C和A->D->C,该方法会从C开始做两次搜索,如果有大量这样的冗余,TLE也就是必然的了。Solution2也是做BFS,但是它没有保存中间路径,用Map保存了每个单词的前继,最短路径找到后,回溯得到所有的最短路径。
Solution1:
public class Solution {
    HashSet<String> dic;
    public List<List<String>> findLadders(String start, String end, Set<String> dict) {
         List<List<String>> reslList = new ArrayList<>();
         if(dict==null||start==null||end==null||dict.size()==0||start.equals("")||end.equals(""))
             return reslList;
    
         List<String> ls = new ArrayList<>();
         ls.add(start);
         reslList.add(ls);
    
         if(start.equals(end))
         {
             return reslList;
         }
     
         dic = new HashSet<>(dict);

         while(!reslList.isEmpty())
        {     
             int count = reslList.size();

             boolean isFound = false;
             ArrayList<String> removeWords = new ArrayList<>();
             while(count-->0)
             {
                 List<String> list = reslList.remove(0);
                 String str = list.get(list.size()-1);
                 int diffchars = 0;

                 for(int i=0;i<str.length();i++)
                 {
                     if(str.charAt(i)!=end.charAt(i))
                         diffchars++;
                 }
                 if(diffchars==1)
                 {
                     isFound = true;
                     list.add(end);
                     reslList.add(list);
                 }
                 if(isFound)
                     continue;        
        
                 char[] chars = str.toCharArray();
                 for(int i=0;i<str.length();i++)
                 {
                     char temp = chars[i];
                     chars[i] = 'a'-1;
                     while(chars[i]++<'z')
                     {
                         if(chars[i]==temp)
                             continue;
                         String s = new String(chars);
                         if(dic.contains(s))
                         {
                             removeWords.add(s);
                             List<String> newList = new ArrayList<>();
                             newList.addAll(list);
                             newList.add(s);
                             reslList.add(newList);
                         }
                     }
                     chars[i] = temp;
                 }
             }
             dic.removeAll(removeWords);
             if(isFound)
             {
                 for(int i=reslList.size()-1;i>=0;i--)
                 {
                     List<String> tmp = reslList.get(i);
                     if(!tmp.get(tmp.size()-1).equals(end))
                     reslList.remove(i);
                 }
                 return reslList;
             }
        }
        return reslList;        
    }
}

Solution2:
public class Solution {
HashSet<String> dic;
HashMap<String, List<String>> preWords = new HashMap<>();
ArrayList<String> list = new ArrayList<>();
List<List<String>> allPath = new ArrayList<>();
 public List<List<String>> findLadders(String start, String end, Set<String> dict) {
        if(dict==null||start==null||end==null||dict.size()==0||start.equals("")||end.equals(""))
         return allPath;
        
        list.add(end);
        if(start.equals(end))
        {
            allPath.add(list);
            return allPath;
        }
        dic = new HashSet<>(dict);

        boolean isFound = false;
        LinkedList<String> curStrings = new LinkedList<>();
        curStrings.add(start);
               
        HashSet<String> visited = new HashSet<>();
        while(!curStrings.isEmpty())
        {
             int count = curStrings.size();
        
             while(count-->0)
             {
                 String str = curStrings.removeFirst();
                 int diffchars = 0;

                 for(int i=0;i<str.length();i++)
                 {
                     if(str.charAt(i)!=end.charAt(i))
                         diffchars++;
                  }
                 if(diffchars==1)
                 {
                     isFound = true;
                     if(preWords.containsKey(end))
                    {
                        preWords.get(end).add(str);
                    }
                    else 
                    {
                        ArrayList<String> newls = new ArrayList<>();
newls.add(str);
                        preWords.put(end, newls);
                    }
             }
             if(isFound)
             continue;       
        
             StringBuilder strb = new StringBuilder(str);
             for(int i=0;i<str.length();i++)
             {
                 char ch = 'a'-1;
                 while(ch++<'z')
                 {
                     strb.setCharAt(i, ch);
                     if(ch==str.charAt(i))
                         continue;
                     String s = strb.toString();

                     if(dic.contains(s))
                     {
                         if(preWords.containsKey(s))
                         {
                             preWords.get(s).add(str);
                         }
                         else 
                         {
                             ArrayList<String> newls = new ArrayList<>();
                             newls.add(str);
                             preWords.put(s, newls);
                        }
                         if(!visited.contains(s))  //这个条件判断很重要,好几次TLE都栽在这上面了
                             curStrings.add(s);
                         visited.add(s);
                     }
                 strb.setCharAt(i, str.charAt(i));
                 }
             }
         }
         dic.removeAll(visited);
         visited.clear();
         if(isFound)
         {
             backTraverse(end, start);
             break;
         }
        }
        return allPath;
    }
   private void backTraverse(String tmp,String start) {
        if(tmp.equals(start))
        {
            allPath.add(new ArrayList<>(list));
            return;
        }
        if(!preWords.containsKey(tmp))
            return;
        for (String str : preWords.get(tmp)) {
            list.add(0,str);
            backTraverse(str, start);
            list.remove(0);
         }
    }
}
0 0
原创粉丝点击