Design a data structure that supports the following two operations:
void addWord(word) bool search(word)
search(word) can search a literal word or a regular expression string containing only letters a-z or .. A . means it can represent any one letter.
Java Solution 1
This problem is similar with Implement Trie. The solution 1 below uses the same definition of a trie node. To handle the “.” case for this problem, we need to search all possible paths, instead of one path.
TrieNode
class TrieNode{ char c; HashMap<Character, TrieNode> children = new HashMap<Character, TrieNode>(); boolean isLeaf; public TrieNode() {} public TrieNode(char c){ this.c = c; } } |
WordDictionary
public class WordDictionary { private TrieNode root; public WordDictionary(){ root = new TrieNode(); } // Adds a word into the data structure. public void addWord(String word) { HashMap<Character, TrieNode> children = root.children; for(int i=0; i<word.length(); i++){ char c = word.charAt(i); TrieNode t = null; if(children.containsKey(c)){ t = children.get(c); }else{ t = new TrieNode(c); children.put(c,t); } children = t.children; if(i == word.length()-1){ t.isLeaf = true; } } } // Returns if the word is in the data structure. A word could // contain the dot character '.' to represent any one letter. public boolean search(String word) { return dfsSearch(root.children, word, 0); } public boolean dfsSearch(HashMap<Character, TrieNode> children, String word, int start) { if(start == word.length()){ if(children.size()==0) return true; else return false; } char c = word.charAt(start); if(children.containsKey(c)){ if(start == word.length()-1 && children.get(c).isLeaf){ return true; } return dfsSearch(children.get(c).children, word, start+1); }else if(c == '.'){ boolean result = false; for(Map.Entry<Character, TrieNode> child: children.entrySet()){ if(start == word.length()-1 && child.getValue().isLeaf){ return true; } //if any path is true, set result to be true; if(dfsSearch(child.getValue().children, word, start+1)){ result = true; } } return result; }else{ return false; } } } |
Java Solution 2 – Using Array Instead of HashMap
class TrieNode{ TrieNode[] arr; boolean isLeaf; public TrieNode(){ arr = new TrieNode[26]; } } public class WordDictionary { TrieNode root; public WordDictionary(){ root = new TrieNode(); } // Adds a word into the data structure. public void addWord(String word) { TrieNode p= root; for(int i=0; i<word.length(); i++){ char c=word.charAt(i); int index = c-'a'; if(p.arr[index]==null){ TrieNode temp = new TrieNode(); p.arr[index]=temp; p=temp; }else{ p=p.arr[index]; } } p.isLeaf=true; } // Returns if the word is in the data structure. A word could // contain the dot character '.' to represent any one letter. public boolean search(String word) { return dfsSearch(root, word, 0); } public boolean dfsSearch(TrieNode p, String word, int start) { if (p.isLeaf && start == word.length()) return true; if (start >= word.length()) return false; char c = word.charAt(start); if (c == '.') { boolean tResult = false; for (int j = 0; j < 26; j++) { if (p.arr[j] != null) { if (dfsSearch(p.arr[j], word, start + 1)) { tResult = true; break; } } } if (tResult) return true; } else { int index = c - 'a'; if (p.arr[index] != null) { return dfsSearch(p.arr[index], word, start + 1); } else { return false; } } return false; } } |
Can anyone tell me why this fails on Leetcode 7th test cases
class WordDictionary {
class TrieNode {
Map children;
Boolean endOfWord;
public TrieNode() {
this.children = new HashMap();
this.endOfWord = false;
}
}
TrieNode root = new TrieNode();
/** Adds a word into the data structure. */
public void addWord(String word) {
if(word == null)
return ;
TrieNode curr = root;
for(int i = 0; i < word.length(); i++){
char c = word.charAt(i);
TrieNode trie = curr.children.get(c);
if(trie == null){
trie = new TrieNode();
curr.children.put(c,trie);
}
curr = trie;
}
curr.endOfWord = true;
}
/** Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter. */
public boolean search(String word) {
TrieNode curr = root;
LinkedList queue = new LinkedList();
queue.add(curr);
int level = 0;
int len = word.length() - 1;
while (!queue.isEmpty() && level <= len) {
char c = word.charAt(level);
int size = queue.size();
for (int i = 0; i < size; i++) {
Map children = queue.remove().children;
TrieNode temp = children.get(c);
if (temp != null) {
if (level == len && temp.endOfWord)
return true;
queue.add(temp);
} else if (c == '.') {
for(Map.Entry entry : children.entrySet()){
queue.add(entry.getValue());
}
} else
return false;
}
level++;
}
return true;
}
}
You can pass the TLE by setting special case for search(“.”)
Just check if root has only one child node
Time out as well. ๐
Did you pass the OJ? TLE here.