前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >LeetCode 208.实现Trie(字典树) - JavaScript

LeetCode 208.实现Trie(字典树) - JavaScript

作者头像
心谭博客
发布2020-04-21 10:43:08
发布2020-04-21 10:43:08
67900
代码可运行
举报
文章被收录于专栏:YuanXinYuanXin
运行总次数:0
代码可运行

实现一个 Trie (前缀树),包含 insert, search, 和 startsWith 这三个操作。

代码语言:javascript
代码运行次数:0
运行
复制
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 构成的。
  • 保证所有输入均为非空字符串。

题目分析

本题的目的是实现一个字典树,这个字典树的主要功能就是 2 个:

  • 存放单词
  • 查找单词是否存在

代码实现

节点单独封装为一个类,它有两个属性:

  • next:next[i]保存着下一个字符i的节点引用
  • isEnd:当前节点是否可以作为一个单词的结束位置

可以看到,节点本身不存储字符,字符是保存在next对象中的 key 中。直观来看,字符是保存在节点之间的连线上的

代码实现如下:

代码语言:javascript
代码运行次数:0
运行
复制
// ac地址: https://leetcode-cn.com/problems/implement-trie-prefix-tree/
// 原文地址:https://xxoo521.com/2020-02-29-trie-prefix-tree/

var TrieNode = function() {
    this.next = {};
    this.isEnd = false;
};

/**
 * Initialize your data structure here.
 */
var Trie = function() {
    this.root = new TrieNode();
};

/**
 * Inserts a word into the trie.
 * @param {string} word
 * @return {void}
 */
Trie.prototype.insert = function(word) {
    if (!word) return false;

    let node = this.root;
    for (let i = 0; i < word.length; ++i) {
        if (!node.next[word[i]]) {
            node.next[word[i]] = new TrieNode();
        }
        node = node.next[word[i]];
    }
    node.isEnd = true;
    return true;
};

/**
 * Returns if the word is in the trie.
 * @param {string} word
 * @return {boolean}
 */
Trie.prototype.search = function(word) {
    if (!word) return false;

    let node = this.root;
    for (let i = 0; i < word.length; ++i) {
        if (node.next[word[i]]) {
            node = node.next[word[i]];
        } else {
            return false;
        }
    }
    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) {
    if (!prefix) return true;

    let node = this.root;
    for (let i = 0; i < prefix.length; ++i) {
        if (node.next[prefix[i]]) {
            node = node.next[prefix[i]];
        } else {
            return false;
        }
    }
    return true;
};

拓展思考:如何删除单词?

题目中的字典树的功能并不完整,它缺失 2 个重要功能:

  • 删除单词
  • 统计单词出现次数

为了解决这个问题,需要给每个 TrieNode 准备 2 个 number 类型变量:

  • path:代表从当前节点经过的单词数量
  • end:代表以当前节点为结束的单词数量

对于「统计单词次数」的功能,搜索完成后,读取最后结束节点的 end 即可。

对于「删除单词」的功能,依次在对路径上节点的 path 减 1。优化的地方是:当 path 为 0 时,说明没有单词经过了,不需要再向下遍历,直接移除以下所有节点即可。

篇幅原因,我把 JavaScript 实现的具有删除功能的 Trie 和测试用例放在了:https://github.com/dongyuanxin/ciy/blob/master/algorithm/trie/better.js

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-02-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 题目分析
  • 代码实现
  • 拓展思考:如何删除单词?
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档