208 实现前缀树
前缀树其实就是字典树,实现一个 Trie (前缀树),包含 insert, search, 和 startsWith 这三个操作。
示例
示例:
1 2 3 4 5 6 7
| Trie trie = new Trie(); trie.insert("apple"); trie.search("apple"); trie.search("app"); trie.startsWith("app"); trie.insert("app"); trie.search("app");
|
问题分析
这个数据结构直接看的极客时间上的课程学来的。但是使用数组来存储 children 的方式确实不错,主要字符集数量有限(26 个英文字母),如果是更大的字符集,使用 map 来存储也不错。
可以用来解决路由表的最长前缀匹配问题,可以使用 trie 树来加快搜索匹配的速度。
Round One
- trie 树主要支持两个操作
- insert - 插入的过程,就是构建这个树的过程,需要动态的创建 children
- search - 搜索的过程,需要验证单词是否完全匹配,因此节点上需要一个 isEndOfWord 的标记
- starsWith - 验证是否是一个合格的前缀,简化版的 search
代码实现
children 是数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| class TrieNode { char: string; isEndOfWord: boolean = false; children: TrieNode[] = [];
constructor(char: string = "") { this.char = char; } }
class Trie { root: TrieNode; constructor() { this.root = new TrieNode(); }
insert(word: string) { let node = this.root; for (let char of word) { const index = char.charCodeAt(0) - 97; if (!node.children[index]) { node.children[index] = new TrieNode(char); } node = node.children[index]; } node.isEndOfWord = true; }
search(word: string) { let node = this.root; for (let char of word) { const index = char.charCodeAt(0) - 97; if (!node.children[index]) { return false; } node = node.children[index]; } return node.isEndOfWord; }
startsWith(word: string) { let node = this.root; for (let char of word) { const index = char.charCodeAt(0) - 97; if (!node.children[index]) { return false; } node = node.children[index]; } return true; } }
|
children 是 map
map 的方法在 leetcode 上更快,应该是因为数组方法里面 charCodeAt 比较耗时吧。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| class TrieNode { char: string; isEndOfWord: boolean = false; children: Map<string,TrieNode> = new Map()
constructor(char:string = ''){ this.char = char; } }
class Trie { root: TrieNode = new TrieNode();
insert(word: string){ let node = this.root; for(let char of word){ if(!node.children.has(char)){ node.children.set(char, new TrieNode(char)); } node = node.children.get(char); } node.isEndOfWord = true; }
search(word: string){ let node = this.root; for(let char of word){ if(!node.children.has(char)){ return false; } node = node.children.get(char); } retur node.isEndOfWord; }
startsWith(word: string){ let node = this.root; for(let char of word){ if(!node.children.has(char)){ return false; } node = node.children.get(char); } return true; }
}
|