使用Trie数据结构实现搜索自动完成功能

本文旨在讨论使用 Java 的搜索自动完成的低级实现,将Trie在用例中使用数据结构。

这是一个示例TrieNode类:

class TrieNode{
Map<Character,TrieNode> children;
boolean isEndOfWord;

    TrieNode(){
children = new HashMap<>();
isEndOfWord = false;
}
}

请注意,我们在这里使用 Map 来存储 Trie 中特定层级的所有字符。
如果问题是按字母顺序返回结果,那么我们别无选择,只能使用 TreeMap,能确保顺序,但会在插入和搜索时耗费时间,因为 TreeMap 查找/插入将耗费 log(n) 时间。

在本文中,我们假设可以按任意顺序返回结果,以使事情变得简单。

另外,假设我们有来自后台的缓存响应。我们可以将其作为自动完成任务的单词来源。让这个输入是单词,假设我们正在搜索一个单词 searchWord 。因此,方法定义可归结为以下内容:

public List suggestedWords(String[] words,
String searchWord) {
for (String word: words) {
insert(word); // insert to Trie }
return search(searchWord); // search in Trie and return results
}

方法 insert(String word) 可以在 Trie 中插入单词。
以下是该方法的示例实现。
请注意,我们需要将最后一个 TrieNode 的 isEndOfWord 标志设置为 true,表示单词的最后一个字符。

private void insert(String word) {
int len = word.length();
TrieNode current = this.root; // member variable pointing to the root of TrieNode for (int i = 0; i < len; i++) {
TrieNode node = current.children.get(word.charAt(i));
if (node == null) {
node = new TrieNode();
current.children.put(word.charAt(i), node);
}
current = node;
}
current.isEndOfWord = true;
}

Trie 可以预先填充,也可以在应用服务器中设置。

因此,实时查询只需直接调用 search(searchWord)。在插入一堆单词后,它看起来就像下面这样(例如:apple, ape, god, good):

现在到了主要部分,即搜索自动完成。
首先,我们需要实现前缀搜索。
我们应该能够在 Trie 中搜索前缀。如果找到匹配,我们就需要搜索该特定 TrieNode 中的完整单词。实时应用将返回 k 个结果,而不是所有单词。
为了实现实时性能,返回 k 个单词是合理的。以下是前缀搜索的实现:

private TrieNode startsWith(String prefix) {
int len = prefix.length();
TrieNode current = this.root;

  for (int i = 0; i < len; i++) {
TrieNode node = current.children.get(prefix.charAt(i));
if (node == null) {
return null;
}
current = node;
}
return current;
}

如果在 Trie 中没有找到前缀,我们将返回 null,否则我们将返回 TrieNode 作为主要搜索的起点。在最坏的情况下,前缀搜索只需要 O(n) 时间。下面,让我用迄今为止定义的所有方法重写搜索函数:

private List search(String searchWord) {
List result = new ArrayList <> ();
TrieNode current = this.root;
int len = searchWord.length();

  current = startsWith(searchWord);
if (current != null) {
List list = new ArrayList <> ();
StringBuilder sb = new StringBuilder(searchWord);
// backtrack(list, current, sb, k); yet to implement. result.addAll(list);
}
return result;
}

请注意,searchWord 可能是一个完整的词,也可能不是。但这并不重要,我们会返回 searchWord 的所有完整单词。我已经对上述代码进行了注释,这些代码还有待讨论/实现。我们可以使用回溯法从前缀 TrieNode 开始遍历所有后续 TrieNode,直到找到一个完整的单词。请参考下面的实现:

private void backtrack(List list,
TrieNode current,
StringBuilder sb,
int k) {
if (list.size() == k) {
return;
}
if (current.isEndOfWord) {
list.add(sb.toString());
}
for (Map.Entry<Character,TrieNode> entry: current.children.entrySet()) {
sb.append(entry.getKey());
backtrack(list, entry.getValue(), sb);
sb.setLength(sb.length() - 1);
}
}

当最多收集到 k 个单词时,我们就停止回溯 Trie。最重要的是,我们会借助 isEndOfWord 标志来收集单词。StringBuilder 的使用在此不言自明。一旦完成回溯,结果将包含所有完整的单词。现在,如果我们需要返回短语列表而不是单词列表,也可以采用同样的解决方案。这里的单词是短语的同义词,所以并不重要。

您可以在实际的编码面试中快速完成编码,改进的空间是无限的!编码快乐

https://www.jdon.com/71720.html

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

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

相关文章

Unity 利用UGUI之Scrollbar制作进度条

在Unity中除了用Slider、Image做进度条&#xff0c;其实用Scrollbar也可以做进度条。 首先&#xff0c;在场景中新建一个Scrollbar组件和一个Text组件&#xff1a; 其次&#xff0c;创建模拟进度的一个脚本&#xff0c;Scrollbar_Progressbar.cs: using System.Collections; …

Linux:linux计算机和windows计算机 之间 共享资源

在前面章节已经介绍过&#xff0c;NFS用于Linux系统之间的文件共享&#xff0c;windows 并不知道 NFS &#xff0c;而是使用 CIFS (Common Internet File System) 的协议机制 来 “共享” 文件。在1991年&#xff0c;Andrew Tridgell 通过逆向工程 实现了 CIFS 协议&#xff0c…

解决“Vue.js not detected”的问题

如果你遇到了“Vue.js not detected”的问题&#xff0c;这通常意味着Vue.js没有正确地加载到你的项目中。以下是一些可能的解决方案&#xff1a; 检查Vue.js的版本&#xff1a;确保你使用的Vue.js版本与你的项目兼容。如果你正在使用一个旧的项目&#xff0c;尝试升级Vue.js到…

中兴通讯5G-A场景突破成果显著,获得行业高度认可

近年来&#xff0c;中兴通讯持续发力5G-A场景&#xff0c;积极进行相关技术研发&#xff0c;为6G时代的到来铺路。2023年12月28日&#xff0c;在2024&#xff08;第二十届&#xff09;ICT行业趋势年会“ICT龙虎榜揭榜盛典”当中&#xff0c;中兴通讯获得“2023年度5G-A场景开拓…

01-06弹性布局

弹性布局 弹性布局 Flex布局&#xff1a;Flex是Flexible Box的缩写&#xff0c;意为”弹性布局”&#xff0c;用来替代float浮动布局&#xff0c;任何一个容器都可以指定为Flex布局 概念&#xff1a;采用Flex布局的元素&#xff0c;称为Flex容器&#xff08;flex container&…

【OCR】实战使用 - ocr 识别图片中的文字

实战使用 - ocr 识别图片中的文字 在Python中&#xff0c;OCR&#xff08;Optical Character Recognition&#xff0c;光学字符识别&#xff09;通常使用一些开源库来实现&#xff0c;如 pytesseract、Tesseract、PIL&#xff08;Python Imaging Library&#xff09;等。以下是…

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

二维数组定义的四种方式&#xff1a; 1&#xff0c;数据类型 数组名[ 行数 ][ 列数 ]&#xff1b; 2&#xff0c;数据类型 数组名[ 行数 ][ 列数 ]{{数据1&#xff0c;数据2}&#xff0c;{数据3&#xff0c;数据4}}&#xff1b; 3&#xff0c;数据类型 数组名[ 行数…

Redis面试题7

Redis 的性能瓶颈有哪些&#xff1f;如何解决&#xff1f; Redis 的性能瓶颈主要有&#xff1a;网络延迟、单线程模型、内存限制等&#xff1b; 解决网络延迟的方法有&#xff1a;使用连接池机制&#xff0c;减少连接的建立和断开次数&#xff1b;使用管道技术&#xff0c;减少…

Webservice,WCF,WebAPI--特点及进化史

WebService、WCF 和 WebAPI 是 Microsoft 在不同时期推出的三种基于不同技术和架构的 Web 服务技术。它们在不同时期的演化中逐步推出&#xff0c;以满足不断变化的需求和技术发展的趋势。 1. WebService&#xff1a;WebService 是一种使用 SOAP 协议和 XML 消息格式的 Web 服…

Vue3导出el-table为execl文件

在开发时遇到了这样的需求&#xff0c;整理之后向大家分享一下&#xff0c;欢迎积极讨论与指正哦 因为在实现表格时使用了分页插件&#xff0c;在导出时只能导出本页的内容&#xff0c;最后选择了这样的方法&#xff1a; 正常显示的表格使用分页后的数据 在这里设置了id 而用…

了解 Node.js 的运行机制:从事件循环到模块系统(上)

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

自己写几个字符串函数

字符串一直是一个很神奇的东西&#xff0c;顾名思义&#xff0c;字符串是由字符所构成的串&#xff0c;而一串字符也就构成了字符串&#xff1b;而我们又知道&#xff0c;字符在内存中是以ASCII码的形式进行存储的&#xff0c;所以说将一切联系起来&#xff0c;我们就可以来研究…

Java索引优先队列设计思路与实现

Java 学习面试指南&#xff1a;https://javaxiaobear.cn 1、实现思路 存储数据时&#xff0c;给每一个数据元素关联一个整数&#xff0c;例如insert(int k,T t),我们可以看做k是t关联的整数&#xff0c;那么我们的实现需要通过k这个值&#xff0c;快速获取到队列中t这个元素&a…

使用使用maven后jstl标签库无法使用

创建maven项目后配置了jstl标签库的依赖&#xff0c;但是一直不行&#xff0c;jsp页面还是原样给我输出&#xff0c;然后去网上找了许多办法&#xff0c;类似于配置文件之类的&#xff0c;结果发现对我并没有什么用&#xff0c;还是原样输出 然后就各种查找&#xff0c;发现了一…

Python中的科学计算和数学建模

Python中的科学计算和数学建模 Python作为一种通用编程语言&#xff0c;在科学计算和数学建模领域有着广泛的应用。通过Python&#xff0c;科学家、工程师和研究人员可以进行复杂的数据分析、建模和可视化。 一、Python中的科学计算 Python的科学计算库非常丰富&#xff0c;…

大数据本地环境搭建-Linux基础环境搭建

1.安装VMware 下载 VMware Workstation Pro | CN 2.配置虚拟网卡 3.Windows网络配置 4.安装centos7.9 Download (centos.org) 4.1 新建虚拟机 如果开机的时候电脑蓝屏使用WindowsR输入optionalfeatures 打开启用或关闭Windows功能->勾选打开以下两项 重启 继续安装ce…

C++力扣题目-- 二叉树层序遍历

102.二叉树的层序遍历(opens new window)107.二叉树的层次遍历II(opens new window)199.二叉树的右视图(opens new window)637.二叉树的层平均值(opens new window)429.N叉树的层序遍历(opens new window)515.在每个树行中找最大值(opens new window)116.填充每个节点的下一个右…

Web前端篇——element-plus组件设置全局中文

背景&#xff1a;在使用el-date-picker组件时&#xff0c;发现组件中的文字默认都是英文。 设置全局中文的方法如下&#xff1a;&#xff08;本文只介绍CDN方式&#xff09; <script src"//unpkg.com/element-plus/dist/locale/zh-cn"></script> <s…

WPS或word中英文字母自动调整大小写,取消自动首字母大写,全部英文单词首字母大小写变换方法

提示&#xff1a;写英文论文时&#xff0c;如何实现英文字母大小写的自动切换&#xff0c;不用再傻傻的一个字母一个字母的编辑了&#xff0c;一篇文章搞定WPS与Word中字母大小写切换 文章目录 一、WPS英文单词大小写自动修改与首字母大写调整英文字母全部由大写变成小写 或 小…

怎样的摆渡系统,能实现安全可管控的跨网数据传输?

大数据时代&#xff0c;数据在流通与传输的过程中&#xff0c;更需要注意到数据的安全防护&#xff0c;护航数据价值。“让数据主宰一切的隐忧”&#xff0c;数字战争的时代&#xff0c;各国早已认识到网络安全愈发重要&#xff0c;数据也成为各国发展的重要武器。 出于安全性和…