211. Add and Search Word - Data structure design (Medium)
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 lettersa-z
or.
. A.
means it can represent any one letter.
For example:
addWord("bad")
addWord("dad")
addWord("mad")
search("pad") -> false
search("bad") -> true
search(".ad") -> true
search("b..") -> true
Note:
You may assume that all words are consist of lowercase lettersa-z
.
You should be familiar with how a Trie works. If not, please work on this problem: Implement Trie (Prefix Tree) first.
Solution 1: Trie
We can use the data structure Trie. First, we need to define a TrieNode class, which has 2 properties.
a TrieNode array, In this problem, only lower-case letters a - z need to be considered, so each TrieNode has at most 26 children and the array's size is 26.
a boolean value to record if current node is the final node of a word. (if the string comprised of characters starting from root to the current node is a word.)
For addWord(), the basic idea is to create a TrieNode corresponding to each letter in the word. When we are done, label the last node to be a word.
class TrieNode {
public TrieNode[] children = new TrieNode[26];
public boolean isWord = false;
}
private TrieNode root;
// initialize your data structure here.
public WordDictionary() { // In the constructor, we initialize the root node.
root = new TrieNode();
}
// Adds a word into the data structure.
public void addWord(String word) { //Iterative O(n);O(1)
if (word == null) {
return;
}
TrieNode node = root;
for (int i = 0; i < word.length(); i++) {
if (node.children[word.charAt(i) - 'a'] == null) {
node.children[word.charAt(i) - 'a'] = new TrieNode();
}
node = node.children[word.charAt(i) - 'a'];
}
node.isWord = true;
}
// Returns if the word is in the data structure.
// A word could contain the dot character '.' to represent any one letter.
/**
* Recursive. O(n); O(n)
* Base case: If start pointer reaches the string's end, check the node's flag.
* If true, there is a word, return true.
* To handle '.'.
* If the character is not a dot:
* | Check if the next node is null, if yes, return false.
* | If not, go on to the next node.
* If the character is a dot, it can match any letter.
* That means we must search every possible subtree/subtrie.
* | So for each child of current node, search the rest characters of the word.
* | If there is one match, return true.
* If there is no match at all, return false.
*/
public boolean search(String word) {
if (word == null) {
return false;
}
return match(word, 0, root);
}
private boolean match(String word, int start, TrieNode node) {
if (start == word.length()) {
return node.isWord;
}
if (word.charAt(start) != '.') {
return node.children[word.charAt(start) - 'a'] != null
&& match(word, start + 1, node.children[word.charAt(start) - 'a']);
} else {
for (int i = 0; i < node.children.length; i++) {
if (node.children[i] != null && match(word, start + 1, node.children[i])) {
return true;
}
}
}
return false;
}
Follow Up:
1.如何优化
在原本的trieNode class中加入一个length的int,记录每个单词的长度,如果匹配单词的长度大于了记录的,就false了
问题是如果记录的是一个较短的单词呢,只是匹配单词的前面一部分?还是得遍历完整个字符串。
2.给定一个字典,查询字符串,要支持类似于“book”, "book...", "..boo..",这种查询
建立tire tree,然后递归查询,follow up是,如果模糊查询只有"...book"和“book...”这两种模式怎么处理,
回答,只要建立顺序tire树,反序tire树,就可以了。
3.一道tag题,加上长时间的讨论data structure for 字典,题目不难,followup问的很细,很基础,考察到了trie
4.