1. 什么是前缀树
Trie 也叫前缀树,核心的思想是空间换时间。利用字符串的公共前缀来降低查询时间的开销,以达到提高效率的目的。
2. 思路
如何判断结尾的地方是曾经被 insert
过的“单词”,我觉得是这题的重点。从题目示例可以看到
trie.insert('apple')
trie.search('app') // false
trie.insert('app')
trie.search('app') // true
apple
和 app
在树中是走的同一条路径。第二次插入 app
后,就好比在路的半途中打了个桩,告诉程序,搜索到这里也是个单词。
在代理里,我用 node.set('end', true)
来做桩。
3. 代码
➥ JavaScript
/**
* Initialize your data structure here.
*/
var Trie = function () {
this.node = new Map()
}
/**
* Inserts a word into the trie.
* @param {string} word
* @return {void}
*/
Trie.prototype.insert = function (word) {
let node = this.node
for (let i = 0; i <= word.length; i++) {
const char = word[i]
if (char !== undefined) {
if (node.has(char)) {
node = node.get(char)
} else {
const nextNode = new Map()
node.set(char, nextNode)
node = nextNode
}
} else {
// 如果节点有一条边是 end,则说明走到这里是曾经被 insert 的 word
node.set('end', true)
}
}
}
/**
* Returns if the word is in the trie.
* @param {string} word
* @return {boolean}
*/
Trie.prototype.search = function (word) {
let node = this.node
for (let i = 0; i < word.length; i++) {
const char = word[i]
if (node.has(char)) {
node = node.get(char)
} else {
return false
}
}
return !!node.get('end')
}
/**
* Returns if there is any word in the trie that starts with the given prefix.
* @param {string} prefix
* @return {boolean}
*/
Trie.prototype.startsWith = function (prefix) {
let node = this.node
for (let i = 0; i < prefix.length; i++) {
const char = prefix[i]
if (node.has(char)) {
node = node.get(char)
} else {
return false
}
}
return true
}
4. 结果
从结果看内存消耗比较多,在变量定义上还有优化空间。
以上仅供参考,谢谢阅读。