【leetcode刷题笔记】Word Ladder II

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.

 

题解:算是leetcode最恶心的一道题了。

Word Ladder一样要用BFS来搜索,但是要解决的问题是如何在BFS中保存路径。我们知道在DFS中 保存路径十分简单,但是在BFS中就很麻烦了。因为我们把点一层一层的放在队列里面,而不是一次把一条路径搜索完全。所以这里引进一种新的类Node如下:

class Node{
        ArrayList<Node> prev;
        String me;
        int dist;
        public Node(String me,int dist){
            this.me = me;
            this.prev = null;
            this.dist = dist;
        }
    }

    使用该类,我们把搜索路径上遇到的每一个单词看成一个节点,me保存该节点对应的单词,dist保存从start单词搜索到该单词的最短距离,prev保存从start到该节点所有长度为dist的路径上该节点的前驱节点。

    这样我们就可以在完成BFS后,从最后一个节点endNode(endNode对应单词end),利用前驱节点信息DFS出startNode到endNode的所有路径了。函数findPath实现这个功能。

    另外在BFS的时候,我们需要一个map,来记录当前访问过哪些单词以及它们对应的节点。假设当前访问的节点是node,它对应的单词是t,我们通过修改t的每一位字母生成新的单词,如果新的单词在dict中且没有建立相应的节点(在map中没有记录),那么就建立相应的节点,并把该节点和单词的对应信息保存在map里面;如果当前生成的单词在dict中且已经有相应的节点,那么我们就看是否node也是它的前驱,如果是,把node加入它的前驱列表就可以了。

    结束的条件是,我们生成了一个单词,它正好等于end,说明找到了从start到end的一条路径(不过为了找到所有到end的路径,所以当前队列中的元素还是要遍历完,因为它们在同一层上,也有可能可以达到end,所以用一个stop变量控制最外层的大循环);或者队列为空,说明找不到从start到end的路径。

最后代码如下:

 1 public class Solution {
 2 private List<List<String>> answer= new ArrayList<List<String>>();
 3     class Node{
 4         ArrayList<Node> prev;
 5         String me;
 6         int dist;
 7         public Node(String me,int dist){
 8             this.me = me;
 9             this.prev = null;
10             this.dist = dist;
11         }
12     }
13     private void findPath(Node endNode,ArrayList<String> result,String start){
14         if(endNode.me.equals(start)){
15             ArrayList<String> temp= new ArrayList<String>(result);
16             answer.add(temp);
17             return;
18         }
19         for(Node n:endNode.prev){
20             result.add(0, n.me);
21             findPath(n, result, start);
22             result.remove(0);
23         }
24     }
25     public List<List<String>> findLadders(String start, String end, Set<String> dict) {
26         
27         if(start == end){
28             List<String> result = new ArrayList<String>();
29             result.add(start);
30             result.add(end);
31             answer.add(result);
32             return answer;
33         }
34         
35         Queue<Node> queue = new LinkedList<Node>();
36         HashMap<String, Node> map = new HashMap<String,Node>();
37         
38         Node startNdoe = new Node(start,0);
39         queue.add(startNdoe);
40         map.put(start, startNdoe);
41         Node endNode = null;
42         int strLen = start.length();
43         boolean stop = false;
44         
45         while(!queue.isEmpty() && !stop){
46             int thisLevel = queue.size();
47             for(int i = 0;i < thisLevel;i++){
48                 Node node = queue.poll();
49                 for(int j = 0;j < strLen;j++){
50                     StringBuilder t = new StringBuilder(node.me);
51                     char ch_t = node.me.charAt(j);
52                     for(char k = 'a';k <= 'z';k++){
53                         if(k != ch_t){
54                             t.setCharAt(j, k);
55                             if(dict.contains(t.toString())){
56                                 Node v = map.get(t.toString());
57                                 if(v == null){
58                                     Node tempNode = new Node(t.toString(),node.dist+1);
59                                     tempNode.prev = new ArrayList<Node>();
60                                     tempNode.prev.add(node);
61                                     queue.add(tempNode);
62                                     map.put(t.toString(), tempNode);
63                                     if(t.toString().equals(end)){
64                                         endNode = tempNode;
65                                         stop = true;
66                                     }
67                                 }
68                                 else {
69                                     if(v.dist == node.dist+1)
70                                         v.prev.add(node);
71                                 }
72                             }
73                         }
74                     }
75                 }
76             }
77         }
78         if(endNode != null){
79             ArrayList<String> result = new ArrayList<String>();
80             result.add(endNode.me);
81             findPath(endNode,result,start);
82         }
83         return answer;
84     }
85 }

 

posted @ 2014-07-27 11:44  SunshineAtNoon  阅读(275)  评论(0编辑  收藏  举报