刷题打卡:字符串操作の实现 Trie (前缀树)

70 阅读2分钟

Offer 驾到,掘友接招!我正在参与2022春招系列活动-刷题打卡任务,点击查看活动详情

一、题目描述:

实现 Trie (前缀树)

Trie(发音类似 "try")或者说 前缀树 是一种树形数据结构,用于高效地存储和检索字符串数据集中的键。这一数据结构有相当多的应用情景,例如自动补完和拼写检查。

请你实现 Trie 类:

Trie() 初始化前缀树对象。 void insert(String word) 向前缀树中插入字符串 word 。 boolean search(String word) 如果字符串 word 在前缀树中,返回 true(即,在检索之前已经插入);否则,返回 false 。 boolean startsWith(String prefix) 如果之前已经插入的字符串 word 的前缀之一为 prefix ,返回 true ;否则,返回 false 。

示例:

输入
["Trie", "insert", "search", "search", "startsWith", "insert", "search"]
[[], ["apple"], ["apple"], ["app"], ["app"], ["app"], ["app"]]
输出
[null, null, true, false, true, null, true]

解释
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

二、思路与实现:

思路: 前缀树事实上就是二叉树的升级版本:多叉树

根节点不存储值,但是会有一个引用一直指向根节点,方便快速寻找

如果把它理解为多叉树,那就是每一个节点都有一个标识,比方说叫isEnd表示是不是单词结尾,默认这个标识为false表示它仅仅是单词的前缀,当真正是单词结尾则设置isEnd为true

插入操作,无非就是沿着根节点找到尽可能多的前缀,实现没有了就沿着后面插入

代码实现:

var Trie = function () {
  this.children = {};
};

/**
 * @param {string} word
 * @return {void}
 */
Trie.prototype.insert = function (word) {
  let node = this.children;
  for (let ch of word) {
    if (!node[ch]) {
      node[ch] = {};
    }
    node = node[ch];
  }
  node.isEnd = true;
};

Trie.prototype.searchPrefix = function (word) {
  let node = this.children;
  for (let ch of word) {
    if (!node[ch]) return false;
    node = node[ch];
  }
  return node;
};
/**
 * @param {string} word
 * @return {boolean}
 */
Trie.prototype.search = function (word) {
  const node = this.searchPrefix(word);
  return node  && node.isEnd != undefined;
};
/**
 * @param {string} prefix
 * @return {boolean}
 */
Trie.prototype.startsWith = function (prefix) {
  return this.searchPrefix(prefix);
};

三、总结:

时间复杂度:初始化为O(1),其余操作为 O(∣S∣),其中∣S∣ 是每次插入或查询的字符串的长度。