211. 添加与搜索单词 - 数据结构设计
请你设计一个数据结构,支持 添加新单词 和 查找字符串是否与任何先前添加的字符串匹配 。
实现词典类 WordDictionary
:
WordDictionary()
初始化词典对象void addWord(word)
将word
添加到数据结构中,之后可以对它进行匹配bool search(word)
如果数据结构中存在字符串与word
匹配,则返回true
;否则,返回false
。word
中可能包含一些'.'
,每个.
都可以表示任何一个字母。
示例:
输入:
["WordDictionary","addWord","addWord","addWord","search","search","search","search"]
[[],["bad"],["dad"],["mad"],["pad"],["bad"],[".ad"],["b.."]]
输出:
[null,null,null,null,false,true,true,true]
解释:
WordDictionary wordDictionary = new WordDictionary();
wordDictionary.addWord("bad");
wordDictionary.addWord("dad");
wordDictionary.addWord("mad");
wordDictionary.search("pad"); // return False
wordDictionary.search("bad"); // return True
wordDictionary.search(".ad"); // return True
wordDictionary.search("b.."); // return True
提示:
1 <= word.length <= 500
addWord
中的word
由小写英文字母组成search
中的word
由 ‘.’ 或小写英文字母组成- 最多调用
50000
次addWord
和search
二、方法一
前缀树
class WordDictionary {
Trie root;
public WordDictionary() {
root = new Trie();
}
public void addWord(String word) {
root.insert(word);
}
public boolean search(String word) {
return dfs(word, 0, root);
}
public boolean dfs(String word, int idx, Trie root) {
if (idx == word.length()) {
return root.getIsEnd();
}
char c = word.charAt(idx);
if (Character.isLetter(c)) {
int cidx = c - 'a';
Trie child = root.getChildren()[cidx];
if (child != null && dfs(word, idx + 1, child)) {
return true;
}
} else {
for (int i = 0; i < 26; i++) {
Trie child = root.getChildren()[i];
if (child != null && dfs(word, idx + 1, child)) {
return true;
}
}
}
return false;
}
class Trie {
Trie[] childen;
boolean isEnd;
public Trie() {
childen = new Trie[26];
isEnd = false;
}
public void insert(String word) {
Trie node = this;
for (int i = 0; i < word.length(); i++) {
char c = word.charAt(i);
int idx = c - 'a';
if (node.childen[idx] == null) {
node.childen[idx] = new Trie();
}
node = node.childen[idx];
}
node.isEnd = true;
}
public Trie[] getChildren() {
return childen;
}
public boolean getIsEnd() {
return isEnd;
}
}
/**
* Your Trie object will be instantiated and called as such:
* Trie obj = new Trie();
* obj.insert(word);
* boolean param_2 = obj.search(word);
* boolean param_3 = obj.startsWith(prefix);
*/
}
/**
* Your WordDictionary object will be instantiated and called as such:
* WordDictionary obj = new WordDictionary();
* obj.addWord(word);
* boolean param_2 = obj.search(word);
*/
复杂度分析
-
时间复杂度:初始化为 O(1),添加单词为O(∣S∣),搜索单词为O(∣Σ∣ ∣S∣ ),其中 ∣S∣ 是每次添加或搜索的单词的长度,Σ 是字符集,这道题中的字符集为全部小写英语字母∣Σ∣=26。
最坏情况下,待搜索的单词中的每个字符都是点号,则每个字符都有∣Σ∣ 种可能。 -
空间复杂度:O(∣T∣⋅∣Σ∣),其中 ∣T∣ 是所有添加的单词的长度之和,Σ 是字符集,这道题中的字符集为全部小写英语字母,∣Σ∣=26。