力扣labuladong一刷day54天前缀树

力扣labuladong一刷day54天前缀树

文章目录

      • 力扣labuladong一刷day54天前缀树
      • 一、208. 实现 Trie (前缀树)
      • 二、648. 单词替换
      • 三、211. 添加与搜索单词 - 数据结构设计
      • 四、1804. 实现 Trie (前缀树) II
      • 五、677. 键值映射

一、208. 实现 Trie (前缀树)

题目链接:https://leetcode.cn/problems/implement-trie-prefix-tree/description/?utm_source=LCUS&utm_medium=ip_redirect&utm_campaign=transfer2china
思路:类似于下图就是前缀树,本质是多叉树,只不过表示子节点的数组是通过字母进行索引的,叶子节点有值来表示。
在这里插入图片描述

class Trie {Node root = null;class Node{int v = 0;Node[] child = new Node[26];}public Trie() {}public void insert(String word) {if (search(word)) {return;}root = addNode(root, word, 0);}public boolean search(String word) {Node node = getNode(root, word);if (node == null || node.v == 0) {return false;}return true;}public boolean startsWith(String prefix) {return getNode(root, prefix) != null;}Node getNode(Node node, String word) {Node p = node;for (int i = 0; i < word.length(); i++) {if (p == null) {return null;}p = p.child[word.charAt(i)-'a'];}return p;}Node addNode(Node node, String word, int i) {if (node == null) {node = new Node();}if (i == word.length()) {node.v = 1;return node;}int c = word.charAt(i) - 'a';node.child[c] = addNode(node.child[c], word, i+1);return node;}
}/*** 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);*/

二、648. 单词替换

题目链接:https://leetcode.cn/problems/replace-words/description/?utm_source=LCUS&utm_medium=ip_redirect&utm_campaign=transfer2china
思路:和上题一样,也是前缀树的应用,只不过多了一个最短前缀替换。

class Solution {public String replaceWords(List<String> dictionary, String sentence) {Trie trie = new Trie();for (String s : dictionary) {trie.insert(s);}String[] split = sentence.split(" ");StringBuilder bf = new StringBuilder();for (String s : split) {String ms = trie.minSearch(s);if ("".equals(ms)) {bf.append(s);}else {bf.append(ms);}bf.append(" ");}bf.deleteCharAt(bf.length()-1);return bf.toString();}class Node {int v = 0;Node[] child = new Node[26];}class Trie {Node root = null;void insert(String word) {root = addNode(root, word, 0);}String minSearch(String word) {Node p = root;for (int i = 0; i < word.length(); i++) {if (p == null) return "";if (p.v == 1) {return word.substring(0, i);}p = p.child[word.charAt(i)-'a'];}if (p != null && p.v == 1) return word;return "";}boolean search(String word) {Node node = getNode(word);if (node == null || node.v == 0) return false;return true;}Node getNode(String word) {Node p = root;for (int i = 0; i < word.length(); i++) {if (p == null) return null;p = p.child[word.charAt(i)-'a'];}return p;}Node addNode(Node node, String word, int i) {if (node == null) {node = new Node();}if (i == word.length()) {node.v = 1;return node;}int c = word.charAt(i)-'a';node.child[c] = addNode(node.child[c], word, i+1);return node;}}
}

三、211. 添加与搜索单词 - 数据结构设计

题目链接:https://leetcode.cn/problems/design-add-and-search-words-data-structure/description/
思路:本题还是前缀树,和上一题类似,唯一不同的点是多了一个模式串匹配。

class WordDictionary {Node root = null;public WordDictionary() {}public void addWord(String word) {root = addNode(root, word, 0);}public boolean search(String word) {return traverse(root, word, 0);}boolean traverse(Node node, String word, int i) {if (node == null) return false;if (i == word.length()) {return node.v == 1;}if ('.' == word.charAt(i)) {for (int j = 0; j < 26; j++) {boolean flag = traverse(node.child[j], word, i + 1);if (flag) return flag;}}else {return traverse(node.child[word.charAt(i)-'a'], word, i+1);}return false;}Node addNode(Node node, String word, int i) {if (node == null) {node = new Node();}if (i == word.length()) {node.v = 1;return node;}int c = word.charAt(i)-'a';node.child[c] = addNode(node.child[c], word, i+1);return node;}}
class Node {int v;Node[] child = new Node[26];
}/*** Your WordDictionary object will be instantiated and called as such:* WordDictionary obj = new WordDictionary();* obj.addWord(word);* boolean param_2 = obj.search(word);*/

四、1804. 实现 Trie (前缀树) II

题目链接:https://leetcode.cn/problems/implement-trie-ii-prefix-tree/description/?utm_source=LCUS&utm_medium=ip_redirect&utm_campaign=transfer2china
思路:本题的前缀树多增加了一个功能就是删除节点,删除节点要考虑的就比较多了,到达value的位置要把数量减一,然后在后序位置删除,如果值大于0直接返回就行,不用删除节点,如果值不大于0就需要看该节点的child是否全为null,如果是返回Null就删除了,不是的话保留。

class Trie {Node root;public Trie() {}public void insert(String word) {root = addNode(root, word, 0);}public int countWordsEqualTo(String word) {Node node = getNode(word);if (null == node) return 0;return node.v;}public int countWordsStartingWith(String prefix) {Node node = getNode(prefix);if (node == null) return 0;return traverse(node, 0);}public void erase(String word) {if (getNode(word) == null) return;root = deleteNode(root, word, 0);}Node deleteNode(Node node, String word, int i) {if (node == null) return null;if (i == word.length()) {if (node.v > 0) node.v--;}else {int c = word.charAt(i)-'a';node.child[c] = deleteNode(node.child[c], word, i+1);}if (node.v > 0) return node;for (int j = 0; j < 26; j++) {if (node.child[j] != null) {return node;}}return null;}int traverse(Node node, int num) {if (node == null) return 0;num = node.v;for (int i = 0; i < 26; i++) {num += traverse(node.child[i], num);}return num;}Node addNode(Node node, String word, int i) {if (node == null) {node = new Node();}if (i == word.length()) {node.v += 1;return node;}int c = word.charAt(i)-'a';node.child[c] = addNode(node.child[c], word, i+1);return node;}Node getNode(String word) {Node p = root;for (int i = 0; i < word.length(); i++) {if (p == null) return null;p = p.child[word.charAt(i)-'a'];}return p;}
}
class Node{int v = 0;Node[] child = new Node[26];
}/*** Your Trie object will be instantiated and called as such:* Trie obj = new Trie();* obj.insert(word);* int param_2 = obj.countWordsEqualTo(word);* int param_3 = obj.countWordsStartingWith(prefix);* obj.erase(word);*/

五、677. 键值映射

题目链接:https://leetcode.cn/problems/map-sum-pairs/description/?utm_source=LCUS&utm_medium=ip_redirect&utm_campaign=transfer2china
思路:关键点是前缀查询,先获取到前缀的节点,然后广度优先遍历,前序位置记录节点位置。

class MapSum {Node root = null;public MapSum() {}public void insert(String key, int val) {root = addNode(root, key, val, 0);}public int sum(String prefix) {Node node = getNode(prefix);if (node == null) return 0;return traverse(node, 0);}int traverse(Node node, int num) {if (node == null) return 0;num = node.v;for (int i = 0; i < 26; i++) {num += traverse(node.child[i], num);}return num;}Node getNode(String word) {Node p = root;for (int i = 0; i < word.length(); i++) {if (p == null) return null;p = p.child[word.charAt(i)-'a'];}return p;}Node addNode(Node node, String word, int value, int i) {if (node == null) {node = new Node();}if (i == word.length()) {node.v = value;return node;}int c = word.charAt(i) - 'a';node.child[c] = addNode(node.child[c], word, value, i+1);return node;}}
class Node {int v = 0;Node[] child = new Node[26];
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/329616.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Hive实战:网址去重

文章目录 一、实战概述二、提出任务三、完成任务&#xff08;一&#xff09;准备数据1、在虚拟机上创建文本文件2、上传文件到HDFS指定目录 &#xff08;二&#xff09;实现步骤1、启动Hive Metastore服务2、启动Hive客户端3、基于HDFS数据文件创建Hive外部表4、利用Hive SQL实…

【MySQL用户管理】

目录&#xff1a; 前言用户管理创建用户删除用户修改用户密码修改用户密码安全检测设置 用户权限添加权限回收权限 总结 前言 剑指offer&#xff1a;一年又13天 用户管理 mysql> show databases; -------------------- | Database | -------------------- | inf…

R304S 指纹识别模块功能实现示例

1 基本通信流程 1.1 UART 命令包的处理过程 1.2 UART 数据包的发送过程 UART 传输数据包前&#xff0c;首先要接收到传输数据包的指令包&#xff0c;做好传输准备后发送成功应答包&#xff0c;最后才开始传输数据包。数据包主要包括&#xff1a;包头、设备地址、包标识、包长…

Java:结束本机端口被占用进程

前言 在实际开发当中我们&#xff0c;往往在idea中将某个服务的启动给关闭了&#xff0c;但是在nacos的某个服务上&#xff0c;我们却可以看到本地别名服务还是在上面挂载着本地再次启动的时候就提示【端口被占用】&#xff0c;今天就说一下如何解决这个问题 操作 点击即可预…

嵌入式(七)看门狗 | 看门狗工作模式 寄存器 时钟系统

文章目录 1 看门狗原理2 功能3 看门狗工作模式4 看门狗控制寄存器5 时钟系统 及其寄存器 1 看门狗原理 看门狗(Watch Dog Timer&#xff0c; WDT)是一种专门用于监测单片机程序运行状态的芯片组件。其实质是一个计数器&#xff0c;一般给看门狗初始一个比较大的数&#xff0c;…

【数据结构—排序—交换排序】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言 一、排序的概念及其运用 1、排序的概念 2、排序运用 3、 常见的排序算法 二、交换排序 1、冒泡排序 1.1算法讲解 1.2冒泡排序的实现&#xff1a; 1.2.1头文件的…

超声波模块的驱动(STM32、51单片机等)

一、前言 本文旨在分享单片机对超声波模块的驱动&#xff0c;测量距离和显示 二、超声波的驱动 1、超声波模块 2、模块性能 &#xff08;1&#xff09;TCT40-16T/R1 压电陶瓷超声传感器&#xff08;通用型&#xff09; 3、接口定义 Vcc、 Trig&#xff08;控制端&#xff09…

thinkphp学习02-目录结构、控制器、路由、配置文件

目录结构 www WEB部署目录&#xff08;或者子目录&#xff09; ├─app 应用目录 │ ├─controller 控制器目录 │ ├─model 模型目录 │ ├─ ... 更多类库目录 │ │ │ ├─common.php 公共函数文件 │ └─event.ph…

聊天Demo

文章目录 参考链接使用前端界面消息窗口平滑滚动至底部vue使用watch监听vuex中的变量变化 参考链接 vue.js实现带表情评论功能前后端实现&#xff08;仿B站评论&#xff09; vue.js实现带表情评论仿bilibili&#xff08;滚动加载效果&#xff09; vue.js支持表情输入 vue.js表…

【AI视野·今日Sound 声学论文速览 第四十期】Wed, 3 Jan 2024

AI视野今日CS.Sound 声学论文速览 Wed, 3 Jan 2024 Totally 4 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Sound Papers Auffusion: Leveraging the Power of Diffusion and Large Language Models for Text-to-Audio Generation Authors Jinlong Xue, Yayue De…

学习笔记——C++一维数组

1&#xff0c;一维数组的定义方式 三种定义方式 1&#xff0c;数据类型 数组名[ 数组长度 ]&#xff1b; 2&#xff0c;数据类型 数组名[ 数组长度 ]{值1&#xff0c;值2&#xff0c;值3 ……}&#xff1b;//未说明的元素用0填补 3&#xff0c;数据类型 数组名[ ]{值1&…

短视频矩阵系统源码--源头技术独立自研框架开发(正规代发布)

一、批量剪辑&#xff08;采用php语言&#xff0c;数学建模&#xff09; 短视频合成批量剪辑的算法主要有以下几种&#xff1a; 1. 帧间插值算法&#xff1a;通过对多个视频的帧进行插帧处理&#xff0c;从而合成一段平滑的短视频。 2. 特征提取算法&#xff1a;提取多个视频…