携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第10天,点击查看活动详情
题目(Design Add and Search Words Data Structure)
链接:https://leetcode-cn.com/problems/design-add-and-search-words-data-structure
解决数:666
通过率:50.4%
标签:深度优先搜索 设计 字典树 字符串
相关公司:facebook amazon google
请你设计一个数据结构,支持 添加新单词 和 查找字符串是否与任何先前添加的字符串匹配 。
实现词典类 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"); // 返回 False
wordDictionary.search("bad"); // 返回 True
wordDictionary.search(".ad"); // 返回 True
wordDictionary.search("b.."); // 返回 True
提示:
1 <= word.length <= 25addWord中的word由小写英文字母组成search中的word由 '.' 或小写英文字母组成- 最多调用
104次addWord和search
思路
看代码
var WordDictionary = function () {
this.root = Object.create(null);
};
WordDictionary.prototype.addWord = function (word) {
let cur = this.root;
for (const ch of word) {
if (!cur[ch]) {
cur[ch] = {};
}
cur = cur[ch];
}
cur.isWord = true;
};
WordDictionary.prototype.search = function (word, cur = this.root) {
let ch = undefined;
for (let i = 0; i < word.length; i++) {
ch = word.charAt(i);
if (ch === '.') {
/**
当 ch === '.'
if(cur还有其他的字符) {
递归search
if(search('.'所处层级的其他字符的剩余部分继续搜索)) {
任意一个搜索成功返回true
}
没搜到返回false
}
其他部分与基础的Trie一致
**/
for (const key in cur) {
if (this.search(word.slice(i + 1, word.length), cur[key])) {
return true;
}
}
return false;
} else if (!cur[ch]) {
return false;
}
cur = cur[ch];
}
return Boolean(cur.isWord);
};
或
// 字典树
class TrieNode {
constructor() {
this.children = new Array(26).fill(0);
this.isEnd = false;
}
insert(word) {
let node = this;
for (let i = 0; i < word.length; i++) {
const ch = word[i];
// 计算当前字符的索引
const index = ch.charCodeAt() - 'a'.charCodeAt();
// 若索引位置还没有单词,则在此新建字典树
if (node.children[index] === 0) node.children[index] = new TrieNode();
node = node.children[index];
}
// 结尾标记单词结束了
node.isEnd = true;
}
getChildren() {
return this.children;
}
isEnd() {
return this.isEnd;
}
}
class WordDictionary {
constructor() {
this.trieRoot = new TrieNode();
}
addWord(word) {
this.trieRoot.insert(word);
}
search(word) {
const dfs = (index, node) => {
// 若索引长度等于单词数,说明遍历完了,返回isEnd
if (index === word.length) return node.isEnd;
const ch = word[index];
if (ch !== '.') {
// 当前字符是字母,必须保证一致
const child = node.children[ch.charCodeAt() - 'a'.charCodeAt()];
if (child && dfs(index + 1, child)) return true;
} else {
// 当前字符是点,点可以代表任何字符
// 只要有一个子节点是true即可
for (const child of node.children) {
if (child && dfs(index + 1, child)) return true;
}
}
// 字符不存在,返回false
return false;
};
return dfs(0, this.trieRoot);
}
}