-
Notifications
You must be signed in to change notification settings - Fork 349
Description
实现一个 Trie (前缀树),包含 insert, search, 和 startsWith 这三个操作。
示例:
Trie trie = new Trie();
trie.insert("apple");
trie.search("apple"); // 返回 true
trie.search("app"); // 返回 false
trie.startsWith("app"); // 返回 true
trie.insert("app");
trie.search("app"); // 返回 true
说明:
你可以假设所有的输入都是由小写字母 a-z 构成的。
保证所有输入均为非空字符串。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/implement-trie-prefix-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
Trie (也叫前缀树、字典树),是一种可以实现快速查找字符串前缀的数据结构。它为单词中的每一个字母开辟一个新的 TrieNode,这个 TrieNode 的结构如下:
let TrieNode = function () {
this.next = new Map();
this.isEnd = false;
};
这里的 next 代表这个字母后面可以继续追加的组合,比如 apple
和ad
它们共用 a
这个 TrieNode,而 a
的 next
表里又保存了 p
和d
的 TrieNode。
在插入的时候,会循环构建这个 TrieNode 树,而在单词的末尾字母的 TrieNode 节点上,会把 isEnd 属性置为 true,用以标识这可以作为一个单词的结尾(注意,是可以作为,并不一定到此为止,因为可能有 ad
和adc
这种两个单词的情况)
而查询某种前缀的单词也就变得很简单,利用前缀中的每个字母不断的循环下去,找到前缀中最后一个单词的 TrieNode,再看它的next
表里有哪些组合,即可找出某个前缀下排列组合的所有可能性。
题解
let TrieNode = function () {
this.next = new Map();
this.isEnd = false;
};
/**
* Initialize your data structure here.
*/
let Trie = function () {
this.root = new TrieNode();
};
/**
* Inserts a word into the trie.
* @param {string} word
* @return {void}
*/
Trie.prototype.insert = function (word) {
let node = this.root;
for (let i = 0; i < word.length; i++) {
let { next } = node;
let trieNode = next.get(word[i]);
if (!trieNode) {
trieNode = new TrieNode();
next.set(word[i], trieNode);
}
node = trieNode;
if (i === word.length - 1) {
node.isEnd = true;
}
}
};
/**
* Returns if the word is in the trie.
* @param {string} word
* @return {boolean}
*/
Trie.prototype.search = function (word) {
let node = this.root;
for (let i = 0; i < word.length; i++) {
let { next } = node;
let trieNode = next.get(word[i]);
if (!trieNode) {
return false;
}
node = trieNode;
}
return node.isEnd;
};
/**
* 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.root;
for (let i = 0; i < prefix.length; i++) {
let { next } = node;
let trieNode = next.get(prefix[i]);
if (!trieNode) {
return false;
}
node = trieNode;
}
return true;
};
/**
* Your Trie object will be instantiated and called as such:
* let obj = new Trie()
* obj.insert(word)
* let param_2 = obj.search(word)
* let param_3 = obj.startsWith(prefix)
*/