IT技术小屋

秋风秋雨,皆入我心

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  38 随笔 :: 1 文章 :: 19 评论 :: 0 Trackbacks
Given two words (start and end), and a dictionary, find the length of shortest transformation sequence 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"]
    As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog",
    return its length 5.
Note:
    1. Return 0 if there is no such transformation sequence.
    2. All words have the same length.
    3. All words contain only lowercase alphabetic characters.

第一个思路是遍历dict中的每一个元素,看是不是和当前word只相差一个字符,如果是则作为新的当前word,直到当前word与target只相差一个字符。实现代码如下:
 1 public class Solution {
 2     public int ladderLength(String start, String end, HashSet<String> dict) {
 3         HashSet<String> trash = new HashSet<String>();
 4         return searchWordLadder(start, end, dict, trash) + 1;
 5     }
 6 
 7     private int searchWordLadder(String start, String end, HashSet<String> dict, HashSet<String> trash) {
 8         if (stringDiff(start, end) == 1) return 1;
 9         if (dict.size() == trash.size()) return 0;
10         int steps = Integer.MAX_VALUE;
11         for (String word : dict) {
12             if (!trash.contains(word) && stringDiff(start, word) == 1) {
13                 trash.add(word);
14                 int lt = searchWordLadder(word, end, dict, trash);
15                 if (lt != 0 && lt < steps) {
16                     steps = lt;
17                 }
18                 trash.remove(word);
19             }
20         }
21         return steps == Integer.MAX_VALUE ? 0 : steps + 1;
22     }
23     
24     private int stringDiff(String s1, String s2) {
25         int diff = 0;
26         int length = s1.length();
27         for (int i = 0; i < length; i++) {
28             if (s1.charAt(i) != s2.charAt(i)) {
29                 diff++;
30             }
31         }
32         return diff;
33     }
34 }
这个算法可以通过小数据测试,但是在大数据下报超时错误。主要问题是算法复杂度较高,由于dict中的单词是乱序的,因此最坏情况下需要遍历所有可能的转换路径才能做出判断。
改变思路,其实可以通过trie树的BFS搜索获得结果,由于BFS是分层遍历的,因此找到一个解之后就可以马上返回,复杂度是O(N),N是原单词的长度。实现代码如下:
 1 public class WordLadder {
 2     public int ladderLength(String start, String end, HashSet<String> dict) {
 3         if (dict.size() == 0)
 4             return 0;
 5         int currentLevel = 1;
 6         int nextLevel = 0;
 7         int step = 1;
 8         boolean found = false;
 9         Queue<String> st = new LinkedList<String>();
10         HashSet<String> visited = new HashSet<String>();
11         st.add(start);
12         while (!st.isEmpty()) {
13             String s = st.remove();
14             currentLevel--;
15             if (stringDiff(s, end) == 1) {
16                 found = true;
17                 step++;
18                 break;
19             } else {
20                 int length = s.length();
21                 StringBuffer sb = new StringBuffer(s);
22                 for (int i = 0; i < length; i++) {
23                     for (int j = 0; j < 26; j++) {
24                         char c = sb.charAt(i);
25                         sb.setCharAt(i, (char) ('a' + j));
26                         if (dict.contains(sb.toString())
27                                 && !visited.contains(sb.toString())) {
28                             nextLevel++;
29                             st.add(sb.toString());
30                             visited.add(sb.toString());
31                         }
32                         sb.setCharAt(i, c);
33                     }
34                 }
35             }
36             if (currentLevel == 0) {
37                 currentLevel = nextLevel;
38                 nextLevel = 0;
39                 step++;
40             }
41         }
42         return found ? step : 0;
43     }
44 
45     private int stringDiff(String s1, String s2) {
46         int diff = 0;
47         int length = s1.length();
48         for (int i = 0; i < length; i++) {
49             if (s1.charAt(i) != s2.charAt(i)) {
50                 diff++;
51             }
52         }
53         return diff;
54     }
55 }
其中利用了队列对trie树进行BFS。
posted on 2013-12-19 09:11 Meng Lee 阅读(1510) 评论(0)  编辑  收藏 所属分类: Leetcode

只有注册用户登录后才能发表评论。


网站导航: