大家好,我是小魔龙,Unity3D软件工程师,VR、AR,虚拟仿真方向,不定时更新软件开发技巧,生活感悟,觉得有用记得一键三连哦。
“设计一个数据结构,支持添加新单词和查找字符串是否与任何以前添加的字符串匹配。”
题目链接:
来源:力扣(LeetCode)
链接: 211. 添加与搜索单词 - 数据结构设计 - 力扣(LeetCode)
请你设计一个数据结构,支持 添加新单词 和 查找字符串是否与任何先前添加的字符串匹配 。
实现词典类 WordDictionary :
示例 1:
输入:
["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"); // 返回 False
wordDictionary.search("bad"); // 返回 True
wordDictionary.search(".ad"); // 返回 True
wordDictionary.search("b.."); // 返回 True
示例 2:
这道题要我们实现一个词典类 WordDictionary,实现单词的添加和搜索。
词典类 WordDictionary可以是使用字典树实现,字典树(前缀树)是一种树形数据结构,用于高效地存储和检索字符串数据集中的键。
字典树的空间复杂度为O(|S|),其中|S|是插入字符串或查询前缀的长度。
对于字典树的操作,插入就没什么好说的,主要是搜索。
对于搜索单词,从字典树根节点开始搜索,由于单词可能包含点号,在搜索的过程中需要处理点号:
重复上面的过程,直到返回false,或者搜索完单词的字符。
代码参考:
class WordDictionary {
private 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);
}
private boolean dfs(String word, int index, Trie node) {
if (index == word.length()) {
return node.isEnd();
}
char ch = word.charAt(index);
if (Character.isLetter(ch)) {
int childIndex = ch - 'a';
Trie child = node.getChildren()[childIndex];
if (child != null && dfs(word, index + 1, child)) {
return true;
}
} else {
for (int i = 0; i < 26; i++) {
Trie child = node.getChildren()[i];
if (child != null && dfs(word, index + 1, child)) {
return true;
}
}
}
return false;
}
}
class Trie {
private Trie[] children;
private boolean isEnd;
public Trie() {
children = new Trie[26];
isEnd = false;
}
public void insert(String word) {
Trie node = this;
for (int i = 0; i < word.length(); i++) {
char ch = word.charAt(i);
int index = ch - 'a';
if (node.children[index] == null) {
node.children[index] = new Trie();
}
node = node.children[index];
}
node.isEnd = true;
}
public Trie[] getChildren() {
return children;
}
public boolean isEnd() {
return isEnd;
}
}
时间复杂度:初始化为O(1),添加单词为O(|S|),搜索单词为O(|∑||S|)
其中|S|是每次添加或搜索的单词的长度,∑为字符集,这道题中的字符集为26个小写英语字母,|∑|=26。
空间复杂度:O(|T| · |∑|)
其中|T|是所有添加的单词的长度之和,∑为字符集,这道题中的字符集为26个小写英语字母,|∑|=26。
总结一下: