力扣 - 208. 实现Trie(前缀树)
题目
思路
在我们生活中很多地方都用到了前缀树:自动补全,模糊匹配,九宫格打字预测等等。。。
虽然说用哈希表也可以实现:是否出现过该单词,该单词出现过几次,但是,在某些情况下,效率并不高:比如我们要查他的前缀是否出现过,那么用哈希表就不好实现了,用前缀树更适合更简单
前缀树:将单词的拆分成每一个字符,构建成树的形状,用空间换时间
假设有b,abc,abd,bcd,abcd,efg,hii 这6个单词,我们构建的树就是如下图这样的:

假如用要查找
abcd是否存在,用最暴力的方法就是查询字串是否存在,存在继续查找下一个,时间复杂度就是\(O(N^2)\)。现在我们用前缀树是这样子查找的:第一个字符是a,那么b、e、h都不用考虑了;然后b,匹配;然后c匹配,右孩子d不用考虑;然后最后一个字符d也匹配,所以字符串存在。因此使用前缀树直接将时间复杂度压缩到了\(O(N)\),但是空间复杂度增加了,因为我们需要构建一棵前缀树来存储字符。前缀树里面存储的都是26个英文小写字母,每次查找的时候,先看看当前单词在children中是否存在,存在的话就查找下一个,如果不存在直接返回false,如果字符串都遍历完了,那么就是存在的
同时我们再TrieNode中添加两个属性:
count和preCount,count用来统计当前单词的个数有多少个,每次插入相同的单词,那么就增加1;preCount用来统计当前字符出现的个数(用来查看某个前缀出现了多少次)
代码
class Trie {
TrieNode root;
public Trie() {
// 初始化根节点
root = new TrieNode();
}
/**
* 插入单词
*/
public void insert(String word) {
TrieNode node = root;
for (int i = 0; i < word.length(); i++) {
// 看看单词中的字符是否在前缀树中,空的话就添加
if (node.children[word.charAt(i) - 'a'] == null) {
node.children[word.charAt(i) - 'a'] = new TrieNode();
}
// 将node指向下一个
node = node.children[word.charAt(i) - 'a'];
node.preCount++;
}
node.count++;
}
/**
* 查找单词是否存在
*/
public boolean search(String word) {
TrieNode node = root;
for (int i = 0; i < word.length(); i++) {
if (node.children[word.charAt(i) - 'a'] == null) {
return false;
}
node = node.children[word.charAt(i) - 'a'];
}
// 如果count大于0,就说明单词存在,反之不存在
return node.count > 0;
}
/**
* 查找前缀是否存在
*/
public boolean startsWith(String prefix) {
TrieNode node = root;
for (int i = 0; i < prefix.length(); i++) {
if (node.children[prefix.charAt(i) - 'a'] == null) {
return false;
}
node = node.children[prefix.charAt(i) - 'a'];
}
return node.preCount > 0;
}
/**
* 前缀树节点
*/
private class TrieNode {
// count代表单词的个数
int count;
// preCount代表字符出现的次数
int preCount;
TrieNode[] children;
TrieNode() {
count = 0;
preCount = 0;
children = new TrieNode[26];
}
}
}
复杂度分析
- 时间复杂度:\(O(word.length)\),其中 N 为数组长度。
- 空间复杂度:\(O(26^N)\),其中 26 意思是最多有26个英文字母, N 即为数组长度
力扣 - 208. 实现Trie(前缀树)的更多相关文章
- 力扣208——实现 Trie (前缀树)
这道题主要是构造前缀树节点的数据结构,帮助解答问题. 原题 实现一个 Trie (前缀树),包含 insert, search, 和 startsWith 这三个操作. 示例: Trie 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 ...
随机推荐
- js repeatify & no for loop
js repeatify & no for loop js repeatify https://www.sitepoint.com/5-typical-javascript-interview ...
- element ui 停止维护了
️♂️ element ui 停止维护了 最近看到有人说 element ui 已经停止维护了,还有点不相信; 不过到 github 验证一下,好像是真的呀 4 个月,没有任何更新了 https:/ ...
- HTML marquee
HTML marquee 跑马灯 https://developer.mozilla.org/en-US/docs/Web/HTML/Element/marquee https://developer ...
- nasm astrchr函数 x86
xxx.asm: %define p1 ebp+8 %define p2 ebp+12 %define p3 ebp+16 section .text global dllmain export as ...
- Datahero Inc利用区块链溯源,造福各行各业
近些年来,随着区块链技术的不断崛起以及快速发展,越多越多的人提出将区块链技术引入到溯源系统当中,溯源也成为了区块链技术的重要应用场景之一. 目前,Datahero inc已建设一整套的溯源平台系统,基 ...
- 记录PyQt5 学习中遇到的一些问题
1 信号与槽的设置中,槽函数不用写括号: btn.clicked.connect(cao()) def cao(): ******** 会报错:argument 1 has unexpected ...
- 总结 接口 final关键字 abstract关键字 static 关键字
final关键字: * final 修饰的方法能被继承 不能被重写 * final修饰的类不能被继承 * final 修饰的变量(基本类型)不能被修改 * final 修饰的成员变量必须初始化 局部变 ...
- AdoptOpenJDK是什么?
要搞清楚AdoptOpenJDK是什么,前提条件是我们需要知道JDK是什么,OpenJDK是什么.明白了JDK和OpenJDK的关系,会容易明白什么是AdoptOpenJDK. JDK是什么? 首先, ...
- vue之provide和inject跨组件传递属性值失败(父组件向子组件传值的两种方式)
简单介绍:当一个子组件需要用到父组件的父组件的某些参数.那么这个时候为了避免组件重复传参,使用vue的依赖注入是个不错的方法,直接在最外层组件设置一个provide,内部不管多少嵌套都可以直接取到最外 ...
- Docker-compose封装mysql并初始化数据以及redis
一.概述 现有一台服务器,需要部署mysql和redis.其中mysql容器,需要在第一次启动时,执行sql文件. redis保持空数据即可. 关于Docker-compose的安装,请参考连接: h ...