Skip to content

实现 Trie (前缀树)-208 #14

@sl1673495

Description

@sl1673495

实现一个 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 代表这个字母后面可以继续追加的组合,比如 applead 它们共用 a 这个 TrieNode,而 anext 表里又保存了 pd 的 TrieNode。

在插入的时候,会循环构建这个 TrieNode 树,而在单词的末尾字母的 TrieNode 节点上,会把 isEnd 属性置为 true,用以标识这可以作为一个单词的结尾(注意,是可以作为,并不一定到此为止,因为可能有 adadc 这种两个单词的情况)

而查询某种前缀的单词也就变得很简单,利用前缀中的每个字母不断的循环下去,找到前缀中最后一个单词的 TrieNode,再看它的next 表里有哪些组合,即可找出某个前缀下排列组合的所有可能性。

image

单词 "leet" 在 Trie 树中的表示
image

题解

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)
 */

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions