【Leetcode 热题 100】208. 实现 Trie (前缀树)

问题背景

T r i e Trie Trie 或者说 前缀树 是一种树形数据结构,用于高效地存储和检索字符串数据集中的键。这一数据结构有相当多的应用情景,例如自动补全和拼写检查。

请你实现 Trie 类:

  • Trie() 初始化前缀树对象。
  • void insert(String word) 向前缀树中插入字符串 w o r d word word。
  • boolean search(String word) 如果字符串 w o r d word word 在前缀树中,返回 t r u e true true(即,在检索之前已经插入);否则,返回 f a l s e false false。
  • boolean startsWith(String prefix) 如果之前已经插入的字符串 w o r d word word 的前缀之一为 p r e f i x prefix prefix,返回 t r u e true true;否则,返回 f a l s e false false。

数据约束

  • 1 ≤ w o r d . l e n g t h , p r e f i x . l e n g t h ≤ 2000 1 \le word.length, prefix.length \le 2000 1≤word.length,prefix.length≤2000
  • w o r d word word 和 p r e f i x prefix prefix 仅由小写英文字母组成
  • insertsearchstartsWith 调用次数 总计 不超过 3 × 1 0 4 3 \times 10 ^ 4 3×104 次

解题过程

前缀树模板题,要求实现的功能比较局限且数据范围不是很大,用类定义就可以。

这种做法需要在每个树节点中开一个长度和字符种类一致的数组,本题中表现为 26 26 26叉树,当数据量很大时,冗余的空间会膨胀得很厉害。

还有一种使用静态二维数组的写法,但是测试用例之间需要清空数组,和这道题的提交方式有点冲突,等遇到要用的时候再练习。

具体实现

java 复制代码
class TreeNode {
    TreeNode[] path = new TreeNode[26];
    boolean end;
}

class Trie {
    private TreeNode root;

    public Trie() {
        root = new TreeNode();
    }
    
    public void insert(String word) {
        TreeNode cur = root;
        for(char c : word.toCharArray()) {
            c -= 'a';
            // 如果当前字符位置不存在路径,那么给它简历一个新结点
            if(cur.path[c] == null) {
                cur.path[c] = new TreeNode();
            }
            // 移动工作指针
            cur = cur.path[c];
        }
        cur.end = true;
    }
    
    public boolean search(String word) {
        return find(word) == 1;
    }
    
    public boolean startsWith(String prefix) {
        return find(prefix) != 0;
    }

    private int find(String word) {
        TreeNode cur = root;
        for(char c : word.toCharArray()) {
            c -= 'a';
            if(cur.path[c] == null) {
                return 0;
            }
            cur = cur.path[c];
        }
        // 返回 1 表示这个单词在此结束,2 表示这个字母不是单词的结尾
        return cur.end ? 1 : 2;
    }
}

/**
 * Your Trie object will be instantiated and called as such:
 * Trie obj = new Trie();
 * obj.insert(word);
 * boolean param_2 = obj.search(word);
 * boolean param_3 = obj.startsWith(prefix);
 */
相关推荐
Jerry14 分钟前
LeetCode 459. 重复的子字符串
算法
海石3 小时前
1500分的题目,确实有实力,不过还是我略胜一筹
算法·leetcode
海石3 小时前
【记忆化搜索】条条大路通AC,走好适合你的那一条,走到后再考虑走得快
算法·leetcode
Jerry5 小时前
LeetCode 151. 反转字符串中的单词
算法
gugucoding6 小时前
31. 【C语言】堆栈与队列的实现
c语言·开发语言·数据结构·链表
ChaoZiLL7 小时前
我的数据结构3——链表(link list)
数据结构·链表
a1117767 小时前
LM 算法迭代过程动画演示(SLAM)
算法
头茬韭菜7 小时前
Context 的生死抉择:四层压缩、截断算法与 Session Memory
算法·ai
Jerry8 小时前
LeetCode 541. 反转字符串 II
算法
Jerry8 小时前
LeetCode 344. 反转字符串
算法