LeetCode: Word Ladder II 解题报告

Word Ladder II

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

Only one letter can be changed at a time
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 II 解题报告

SOLUTION 1:

这题做得真累,主页君差点一口老血吐在屏幕上,感觉一不小心就会超时了。

其实最后还是可以采用跟Word Ladder 1一样的解法。使用BFS遍历可能的解。不同的有以下几点:

1. 分层次遍历的时候,不要把找到的解的单词直接放在MAP中,而是可以放在别的一个临时的MAP中,一层遍历完成后,再统一加到MAP。这样做的上的是:

如果本层找到一个单词比如Word,本层的其它单词如果也可以到达Word,我们仍然要把它的解都记下来。

2. 添加到队列的时候,也要判断是不是一个新的单词(在临时MAP中查一下),是新的才能放在Queue中,否则因为1的关系,我们会计算某个单词的所有的解,所以会一直访问它。为了避免重复加入一个单词,这一步是有必要的。

3. 与Word Ladder1中的set不同,我们使用一个hasmap来记录路径中的单词,另外,每一个单词对应的value是一个string的list,记录到达此单词的所有的可能的路径。创建这些路径的方法是:把前节点的所有的路径加上当前单词,复制一份加过来即可。

REF: http://blog.csdn.net/whuwangyi/article/details/21611433

 1 public class Solution {

 2     public static List<List<String>> findLadders(String start, String end, Set<String> dict) {

 3         if (start == null || end == null) {

 4             return null;

 5         }

 6         

 7         Queue<String> q = new LinkedList<String>();

 8         

 9         // 存储每一个单词对应的路径

10         HashMap<String, List<List<String>>> map = new HashMap<String, List<List<String>>>();

11         

12         // 标记在某一层找到解

13         boolean find = false;

14         

15         // store the length of the start string.

16         int lenStr = start.length();

17         

18         List<List<String>> list = new ArrayList<List<String>>();

19         

20         // 唯一的路径

21         List<String> path = new ArrayList<String>();

22         path.add(start);

23         list.add(path);

24         

25         // 将头节点放入

26         map.put(start, list);

27         q.offer(start);

28         

29         while (!q.isEmpty()) {

30             int size = q.size();

31             

32             HashMap<String, List<List<String>>> mapTmp = new HashMap<String, List<List<String>>>();    

33             for (int i = 0; i < size; i++) {

34                 // get the current word.

35                 String str = q.poll();

36                 for (int j = 0; j < lenStr; j++) {

37                     StringBuilder sb = new StringBuilder(str);

38                     for (char c = 'a'; c <= 'z'; c++) {

39                         sb.setCharAt(j, c);

40                         String tmp = sb.toString();

41                         

42                         // 1. 重复的单词,不需要计算。因为之前一层出现过,再出现只会更长

43                         // 2. 必须要在字典中出现

44                         if (map.containsKey(tmp) || (!dict.contains(tmp) && !tmp.equals(end))) {

45                             continue;

46                         }

47                         

48                         // 将前节点的路径提取出来

49                         List<List<String>> pre = map.get(str);

50                         

51                         // 从mapTmp中取出节点,或者是新建一个节点

52                         List<List<String>> curList = mapTmp.get(tmp);

53                         if (curList == null) {

54                             // Create a new list and add to the end word.

55                             curList = new ArrayList<List<String>>();

56                             mapTmp.put(tmp, curList);

57                         

58                             // 将生成的单词放入队列,以便下一次继续变换

59                             // 放在这里可以避免Q重复加入

60                             q.offer(tmp);

61                         }

62                         

63                         // 将PRE的path 取出,加上当前节点,并放入curList中

64                         for(List<String> pathPre: pre) {

65                             List<String> pathNew = new ArrayList<String>(pathPre);

66                             pathNew.add(tmp);

67                             curList.add(pathNew);

68                         }

69                         

70                         if (tmp.equals(end)) {

71                             find = true;

72                         }

73                     }

74                 }

75             }

76             

77             if (find) {

78                 return mapTmp.get(end);

79             }

80             

81             // 把当前层找到的解放在MAP中。

82             // 使用2个map的原因是:在当前层中,我们需要把同一个单词的所有的解全部找出来.

83             map.putAll(mapTmp);

84         }

85         

86         // 返回一个空的结果

87         return new ArrayList<List<String>>();

88     }

89 }

 2014.12.18 Redo:

做了一个小小的优化,拿掉了Find Flag:

 1 public class Solution {

 2     public static List<List<String>> findLadders(String start, String end, Set<String> dict) {

 3         List<List<String>> ret = new ArrayList<List<String>>();

 4         if (start == null || end == null || dict == null) {

 5             return ret;

 6         }

 7         

 8         HashMap<String, List<List<String>>> map = new HashMap<String, List<List<String>>>();

 9         

10         // Store the map of the current level.

11         HashMap<String, List<List<String>>> mapTmp = new HashMap<String, List<List<String>>>();

12         

13         Queue<String> q = new LinkedList<String>();

14         q.offer(start);

15         

16         List<List<String>> listStart = new ArrayList<List<String>>();

17         

18         // 唯一的路径

19         List<String> path = new ArrayList<String>();

20         path.add(start);

21         listStart.add(path);

22         

23         // 将头节点放入

24         map.put(start, listStart);

25         

26         while (!q.isEmpty()) {

27             int size = q.size();

28             

29             for (int i = 0; i < size; i++) {

30                 String s = q.poll();

31                 

32                 int len = s.length();

33                 for (int j = 0; j < len; j++) {

34                     StringBuilder sb = new StringBuilder(s);

35                     for (char c = 'a'; c <= 'z'; c++) {

36                         // Bug 2: should seperate the setCharAt(j, c) function and the sb.toString() function.

37                         sb.setCharAt(j, c);

38                         String tmp = sb.toString();

39                         

40                         // 1. 不在字典中,并且不是end.

41                         // 2. 前面的map中已经出现过

42                         

43                         // Bug 1: map should use containsKey;

44                         if ((!dict.contains(tmp) && !tmp.equals(end)) || map.containsKey(tmp)) {

45                             continue;

46                         }

47                         

48                         // Try to get the pre list.

49                         List<List<String>> pre = map.get(s);

50                         

51                         // 从mapTmp中取出节点,或者是新建一个节点

52                         List<List<String>> curList = mapTmp.get(tmp);

53                         if (curList == null) {

54                             curList = new ArrayList<List<String>>();

55                             

56                             // Only offer new string to the queue.

57                             // 将生成的单词放入队列,以便下一次继续变换

58                             // 放在这里可以避免Q重复加入

59                             q.offer(tmp);

60                             

61                             // create a new map.

62                             mapTmp.put(tmp, curList);

63                         }

64                         

65                         // 将PRE的path 取出,加上当前节点,并放入curList中

66                         for (List<String> strList: pre) {

67                             // Should create a new list. 

68                             List<String> strListNew = new ArrayList<String>(strList);

69                             strListNew.add(tmp);

70                             curList.add(strListNew);

71                         }

72                     }

73                 }

74             }

75             

76             if (mapTmp.containsKey(end)) {

77                 return mapTmp.get(end);

78             }

79             

80             // add the tmp map into the map.

81             map.putAll(mapTmp);

82         }

83         

84         return ret;

85     }

86 }
View Code

 

SOLUTION 2:

http://www.ninechapter.com/solutions/

 

GITHUB:

https://github.com/yuzhangcmu/LeetCode_algorithm/blob/master/string/FindLadders.java

https://github.com/yuzhangcmu/LeetCode_algorithm/blob/master/string/FindLadders_1218_2014.java

你可能感兴趣的:(LeetCode)