力扣208——实现 Trie (前缀树)
这道题主要是构造前缀树节点的数据结构,帮助解答问题。
原题
实现一个 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 构成的。
- 保证所有输入均为非空字符串。
原题url:https://leetcode-cn.com/problems/implement-trie-prefix-tree/
解题
前缀树的意义
我们用前缀树这种数据结构,主要是用在在字符串数据集中搜索单词的场景,但针对这种场景,我们也可以使用平衡树和哈希表,而且哈希表可以在O(1)时间内寻找到键值。那为什么还要前缀树呢?
原因有3:
- 前缀树可以找到具有同意前缀的全部键值。
- 前缀树可以按词典枚举字符串的数据集。
- 前缀树在存储多个具有相同前缀的键时可以使用较少的空间,只需要
O(m)的时间复杂度,其中 m 为键长。在平衡树中查找键值却需要O(m log n),其中 n 是插入的键的数量;而哈希表随着大小的增加,会出现大量的冲突,时间复杂度可能增加到O(n)。
构造前缀树的节点结构
既然是树,肯定也是有根节点的。至于其节点结构,需要有以下特点:
- 最多 R 个指向子结点的链接,其中每个链接对应字母表数据集中的一个字母。本题中假定 R 为 26,小写拉丁字母的数量。
- 布尔字段,以指定节点是对应键的结尾还是只是键前缀。

接下来让我们看看节点结构的代码:
class TrieNode {
TrieNode[] nodes;
boolean isEnd;
public TrieNode() {
// 26个小写英文字母
nodes = new TrieNode[26];
// 当前是否已经结束
isEnd = false;
}
/**
* 当前节点是否包含字符 ch
*/
public boolean contains(char ch) {
return nodes[ch - 'a'] != null;
}
/**
* 设置新的下一个节点
*/
public TrieNode setNode(char ch, TrieNode node) {
// 判断当前新的节点是否已经存在
TrieNode tempNode = nodes[ch - 'a'];
// 如果存在,就直接返回已经存在的节点
if (tempNode != null) {
return tempNode;
}
// 否则就设置为新的节点,并返回
nodes[ch - 'a'] = node;
return node;
}
/**
* 获取 ch 字符
*/
public TrieNode getNode(char ch) {
return nodes[ch - 'a'];
}
/**
* 设置当前节点为结束
*/
public void setIsEnd() {
isEnd = true;
}
/**
* 当前节点是否已经结束
*/
public boolean isEnd() {
return isEnd;
}
}
接下来就是真正的前缀树的结构:
class Trie {
/**
* 根节点
*/
TrieNode root;
/** Initialize your data structure here. */
public Trie() {
root = new TrieNode();
}
/** Inserts a word into the trie. */
public void insert(String word) {
TrieNode before = root;
TrieNode node;
// 遍历插入单词中的每一个字母
for (int i = 0; i < word.length(); i++) {
node = new TrieNode();
node = before.setNode(word.charAt(i), node);
before = node;
}
// 设置当前为终点
before.setIsEnd();
}
/** Returns if the word is in the trie. */
public boolean search(String word) {
TrieNode before = root;
TrieNode temp;
// 遍历查找
for (int i = 0; i < word.length(); i++) {
temp = before.getNode(word.charAt(i));
if (temp == null) {
return false;
}
before = temp;
}
// 且最后一个节点也是终点
return before.isEnd();
}
/** Returns if there is any word in the trie that starts with the given prefix. */
public boolean startsWith(String prefix) {
TrieNode before = root;
TrieNode temp;
// 遍历查找
for (int i = 0; i < prefix.length(); i++) {
temp = before.getNode(prefix.charAt(i));
if (temp == null) {
return false;
}
before = temp;
}
return true;
}
}
提交OK,执行用时:43 ms,内存消耗:55.3 MB,虽然只战胜了87.40%的提交,但试了一下最快的那个代码,和我这个方法在时间上基本没什么差别,应该是当初提交的时候测试用例没有那么多吧。
总结
以上就是这道题目我的解答过程了,不知道大家是否理解了。这道题目可能需要专门去理解一下前缀树的用途,这样可以有助于构造前缀树的结构。
有兴趣的话可以访问我的博客或者关注我的公众号、头条号,说不定会有意外的惊喜。
公众号:健程之道


力扣208——实现 Trie (前缀树)的更多相关文章
- 力扣 - 208. 实现Trie(前缀树)
目录 题目 思路 代码 复杂度分析 题目 208. 实现 Trie (前缀树) 思路 在我们生活中很多地方都用到了前缀树:自动补全,模糊匹配,九宫格打字预测等等... 虽然说用哈希表也可以实现:是否出 ...
- 力扣208. 实现 Trie (前缀树)
原题 以下是我的代码,就是简单的字符串操作,可以ac但背离了题意,我之前没接触过Trie 1 class Trie: 2 3 def __init__(self): 4 ""&qu ...
- Java实现 LeetCode 208 实现 Trie (前缀树)
208. 实现 Trie (前缀树) 实现一个 Trie (前缀树),包含 insert, search, 和 startsWith 这三个操作. 示例: Trie trie = new Trie() ...
- [leetcode] 208. 实现 Trie (前缀树)(Java)
208. 实现 Trie (前缀树) 实现Trie树,网上教程一大堆,没啥可说的 public class Trie { private class Node { private int dumpli ...
- leetcode 208. 实现 Trie (前缀树)
实现一个 Trie (前缀树),包含 insert, search, 和 startsWith 这三个操作. 示例: Trie trie = new Trie(); trie.insert(" ...
- 4.14——208. 实现 Trie (前缀树)
前缀树(字典树)是经典的数据结构,以下图所示: 本来处理每个节点的子节点集合需要用到set,但是因为输入规定了只有26个小写字母,可以直接用一个[26]的数组来存储. 关于ASCII代码: Java ...
- 208. 实现 Trie (前缀树)
主要是记录一下这个数据结构. 比如这个trie树,包含三个单词:sea,sells,she. 代码: class Trie { bool isWord; vector<Trie*> chi ...
- 【LeetCode】208. Implement Trie (Prefix Tree) 实现 Trie (前缀树)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 公众号:负雪明烛 本文关键词:Leetcode, 力扣,Trie, 前缀树,字典树,20 ...
- 第15个算法-实现 Trie (前缀树)(LeetCode)
解法代码来源 :https://blog.csdn.net/whdAlive/article/details/81084793 算法来源:力扣(LeetCode)链接:https://leetcode ...
随机推荐
- IntelliJ IDEA和Eclipse设置JVM运行参数
打开 IDEA 安装目录,看到有一个 bin 目录,其中有两个 vmoptions 文件,需针对不同的JDK进行配置: 32 位:idea.exe.vmoptions64 位:idea64.exe.v ...
- JQuery完整验证&密码的显示与隐藏&验证码
HTML <link href="bootstrap.css" rel="stylesheet"> <link href="gloa ...
- @noi.ac - 441@ 你天天努力
目录 @description@ @solution@ @accepted code@ @details@ @description@ 你天天努力,还是比不上小牛,因为小牛在家中套路.于是你决定去拜访 ...
- 一个简单的hexo搭建博客网站的故事
首先安装hexo mkdir hexo #创建一个文件夹 cd hexo #切换到hexo目录下面 npm install -g hexo-cli npm install hexo --save 然后 ...
- xUtils框架的介绍(二)
xUtils中有四大组件可以供我们使用,分别是ViewUtils.HttpUtils.BitmapUtils以及DbUtils.如果你没能先读一下我的上一篇文章,那么请你移步过去先整体了解一下,再回过 ...
- Codeforces Round #182 (Div. 1 + Div. 2)
A. Eugeny and Array \(r-l+1\)是奇数时,和显然无法为0. 奇数的情况需要判断-1和1的个数是否大于等于长度的一半. B. Eugeny and Play List 模拟. ...
- CodeForces 620E"New Year Tree"(DFS序+线段树+状态压缩)
传送门 •题意 给你一颗 n 个节点的树,每个节点被染上了颜色: 有 m 次操作,每次操作的类型有两种 1 v c : 将以 v 为根的子树的结点全部涂成 c 2 v : 询问以 v 为根的子树的结点 ...
- 【codeforces 789A】Anastasia and pebbles
[题目链接]:http://codeforces.com/contest/789/problem/A [题意] 有n种物品,每种物品有wi个; 你有两个口袋,每个口袋最多装k个物品; 且口袋里面只能装 ...
- [转]Android自定义控件:进度条的四种实现方式(Progress Wheel的解析)
最近一直在学习自定义控件,搜了许多大牛们Blog里分享的小教程,也上GitHub找了一些类似的控件进行学习.发现读起来都不太好懂,就想写这么一篇东西作为学习笔记吧. 一.控件介绍: 进度条在App中非 ...
- C# 命令行如何静默调用 del 删除文件
如果在 C# 命令行调用 del 删除文件,很多时候会提示是否需要删除,本文告诉大家如何调用命令行的时候静默删除 在C# 命令行 调用 del 删除文件的时候,会提示是否删除,通过在命令行加上 \Q ...