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.