Word Ladder

Given two words (start and end), and a dictionary, find all 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

 

Note:

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

尝试用Trie 来实现这个。

最后TLE(out of time),不过算法已经正确了。 

使用Trie,扩展性更好。 可以时时的加减dict里面的word, 也可以被多次调用。

  1 package leetcode;

  2 

  3 import java.util.ArrayList;

  4 import java.util.HashSet;

  5 import java.util.Iterator;

  6 import java.util.List;

  7 import java.util.Set;

  8 

  9 //implement wordLadder with Trie.

 10 /*

 11  * 如果这个函数要多次被调用,怎么办?

 12  * 因为我每次都用挨个修改字母的办法来寻找新word,但如果能先对dictionary做个预处理,弄个从word到set of words之间的mapping,那么每轮BFS就可以省去寻找新词的时间。预处理字典的复杂度也是O(size of dictionary) * (length of string) * 26。最终可以用一个Hash<String, Set<String>>来表示这个mapping关系。

 13  * 

 14  * 如果这个字典要增加/移除单词怎么办?

 15  * 增加的话,只需要对新单词做同样的事情:修改每个字母找下一个单词,然后那个被找到下一个单词的mapping里同时也添加进新单词。因为这个关系是可互换的,如果wordA => wordB, 那么wordB => wordA。

 16  * 删除的时候同理,对于map.get(toBeRemoved)里的所有单词的mapping集合都删掉这个toBeRemoved,然后再从map里面去掉它自己,写出来的代码大概是这样:

 17  * for (String s : map.get(toBeRemoved)) map.get(s).remove(toBeRemoved);

 18  * map.remove(toBeRemoved);

 19  * 这个地方我一开始没注意到可以互换,以为还得预处理一个反方向的mapping,经过面试官两次提醒才发现了这个规律……

 20  * 

 21  * 如果这个字典变得很庞大,这个mapping和字典本身就太占空间了,怎么处理?

 22  * 用trie记录所有单词,每个node用一个bit记录这个node是否为一个单词,并且有一个set<myTrieNode>的field记录他可以变成的其他单词。至于如何构建这个field,利用trie的特性,可以用回溯的方法非常简单地找到可变过去的单词(在碰到公共ancestor之前,路径上的node个数必须相同,这个用于保证长度,并且至多只有一个字母不同,用于满足mapping的条件)

 23  * 至此……时间终于用完了,问了下他的team的情况,就结束了……

 24  * 

 25  * */

 26 

 27 class myTrieNode{

 28     Boolean isWord;

 29     myTrieNode[] childList;

 30     Integer freq;

 31     char val;

 32     String word;

 33     

 34     public myTrieNode(){//use to generate root of Trie

 35         this.freq = 0;

 36         this.childList = new myTrieNode[26];

 37         this.isWord = false;

 38     }

 39     

 40     public myTrieNode(char c){

 41         this.val = c;

 42         this.freq = 1;

 43         this.childList = new myTrieNode[26];

 44     }

 45     

 46     public String containsWord(String s){

 47         if(s == null || s.length() == 0){

 48             if(this.word != null && this.isWord == true) return this.word;

 49             else return "";

 50         }

 51         int len = s.length();

 52         myTrieNode cur = this;

 53         for(int i = 0; i < len; i ++){

 54             char c = s.charAt(i);

 55             if(cur.childList[c - 'a'] != null){

 56                 cur = cur.childList[c - 'a'];

 57             }else{

 58                 return null;

 59             }

 60         }

 61         return cur.isWord == true ? cur.word : null;

 62     }

 63 }

 64 class myTrie{

 65     myTrieNode root;

 66     

 67     public myTrie(){

 68         this.root = new myTrieNode();

 69     }

 70     

 71     public void insert(String word){

 72         if(word == null || word.length() == 0) return;

 73         int len = word.length();

 74         myTrieNode cur = this.root;

 75         for(int i = 0; i < len; i ++){

 76             char c = word.charAt(i);

 77             if(cur.childList[c - 'a'] == null){

 78                 cur.childList[c - 'a'] = new myTrieNode(c);

 79             }else{

 80                 cur.childList[c - 'a'].freq ++;

 81             }

 82             cur = cur.childList[c - 'a'];

 83             if(i == word.length() - 1){

 84                 cur.isWord = true;

 85                 cur.word = word;

 86             } 

 87         }

 88     }

 89     

 90 }

 91 public class WordLadder {

 92         

 93         

 94         private static myTrie trie;

 95         private static List<List<String>> result;

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

 97             trie = generateTrie(dict);

 98             trie.insert(end);

 99             result = new ArrayList<List<String>> ();

100             ArrayList<String> row = new ArrayList<String>();

101             row.add(start);

102             findLadderSequence(start, end, row, new HashSet<String>());

103             return result;

104         }

105         

106         private static void findLadderSequence(String start, String end, ArrayList<String> row, HashSet<String> usedSet){

107             if(start.equals(end)){

108                 result.add(row);

109             }

110             myTrieNode cur = trie.root;

111             myTrieNode next = cur;

112             for(int i = 0; i < start.length(); i ++){

113                 char c = start.charAt(i);

114                 for(int j = 0; j < 26; j ++){

115                     if(cur.childList[j] != null && cur.childList[j].val == c){

116                         next = cur.childList[j];

117                     }

118                     if(cur.childList[j] != null && cur.childList[j].val != c){

119                         String tmp = cur.childList[j].containsWord(start.substring(i + 1));

120                         if(tmp != null && !usedSet.contains(tmp)){

121                             row.add(tmp);

122                             usedSet.add(tmp);

123                             findLadderSequence(tmp, end, new ArrayList<String>(row), new HashSet<String>(usedSet));

124                             row.remove(row.size() - 1);

125                             usedSet.remove(tmp);

126                         }

127                     }

128                 }

129                 cur = next;

130             }

131             

132         }

133         

134         private static myTrie generateTrie(Set<String> dict){

135             myTrie trie = new myTrie();

136             if(dict.isEmpty()) return trie;

137             //generate Trie for dictionary

138             Iterator it = dict.iterator();

139             while(it.hasNext()){

140                 String word = (String)it.next();

141                 trie.insert(word);

142             }

143             return trie;

144         }

145         

146     public static void main(String[] args){

147         String start = "hit";

148         String end = "cog";

149         Set<String> dict = new HashSet<String>();

150         dict.add("hot");

151         dict.add("dot");

152         dict.add("dog");

153         dict.add("lot");

154         dict.add("log");

155         findLadders(start, end, dict);

156         System.out.println(result);

157     }

158 }

 Output:

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

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

[hit, hot, dot, dog, cog],

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

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

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

[hit, hot, lot, log, cog],

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

你可能感兴趣的:(word)