小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
本文已参与「掘力星计划」,赢取创作大礼包,挑战创作激励金。
说明
字典树:又称单词查找树,Trie树,是一种树形结构,哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。
字典树模板:
public class WordTree {
/**
* 下一级节点
*/
private WordTree[] next;
/**
* 单词结尾标识
*/
private boolean isEnd;
public WordTree() {
this.next = new WordTree[26];
}
/**
* 添加单词
*/
public void addWrod(String word){
WordTree wordTree = this;
for(char w : word.toCharArray()){
// 建立下级字符节点
if (null == wordTree.next[w - 'a']){
wordTree.next[w - 'a'] = new WordTree();
}
wordTree = wordTree.next[w - 'a'];
}
// 单词新增完成,修改标识
wordTree.isEnd = true;
}
/**
* 查找单词
*/
public boolean search(String word){
WordTree wordTree = this;
// 遍历下级字符节点判断是否存在该字符
for(char w : word.toCharArray()){
if (null == wordTree.next[w - 'a']){
return false;
}
wordTree = wordTree.next[w - 'a'];
}
// 返回结果
return wordTree.isEnd;
}
}
题目
请你设计一个数据结构,支持 添加新单词 和 查找字符串是否与任何先前添加的字符串匹配 。
实现词典类 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 <= 500addWord中的word由小写英文字母组成search中的word由 '.' 或小写英文字母组成- 最多调用
50000次addWord和search
解题思路
看到单词以及查找字符串,那么很容易就可以想到通过字典树的方式来实现。稍有不同的是,在搜索字符串的过程中,我们需要针对'.'进行模糊查询,这个就得修改常规的字典树搜索逻辑,采用搜索算法来判断该字符串是否存在。
代码实现
class WordDictionary {
/**
* 下一级节点
*/
private WordDictionary[] next;
/**
* 单词结尾标识
*/
private boolean isEnd;
public WordDictionary() {
this.next = new WordDictionary[26];
}
/**
* 添加单词
*/
public void addWord(String word) {
WordDictionary wordDictionary = this;
for(char w : word.toCharArray()){
if(null == wordDictionary.next[w - 'a']){
wordDictionary.next[w - 'a'] = new WordDictionary();
}
wordDictionary = wordDictionary.next[w - 'a'];
}
wordDictionary.isEnd = true;
}
/**
* 查找单词
*/
public boolean search(String word) {
// 由于该题需要进行模糊搜索,这里采用DFS的方式来判断
return searchAll(word.toCharArray(), 0, this);
}
/**
* @param word 字符串
* @param index 索引
* @param words 节点
*/
public boolean searchAll(char[] word, int index, WordDictionary words){
for(int i = index; i < word.length; ++i){
// 模糊搜索需要遍历所有已存在的子节点
if('.' == word[i]){
boolean res = false;
for(WordDictionary w : words.next){
if(w != null && !res){
res |= searchAll(word, i + 1, w);
}
}
return res;
}
// 子节点不存在,直接返回
if(words.next[word[i] - 'a'] == null){
return false;
}else{
// 字节点存在,则继续向下搜索
words = words.next[word[i] - 'a'];
}
}
// 返回结果
return words.isEnd;
}
}
复杂度分析
- 时间复杂度:
addWord操作为,serach操作为。 - 空间复杂度:。
L为字符串长度,M为子节点占用空间,本题为26
相似题目
212. 单词搜索 II:leetcode-cn.com/problems/wo…
208. 实现 Trie (前缀树):leetcode-cn.com/problems/im…
最后
文章有写的不好的地方,请大佬们不吝赐教,错误是最能让人成长的,愿我与大佬间的距离逐渐缩短!
如果觉得文章对你有帮助,请 点赞、收藏、关注、评论 一键四连支持,你的支持就是我创作最大的动力!!!