【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 }

 

你可能感兴趣的:(LeetCode)