当前位置: 首页 > news >正文

学习记录:js算法(六十一):添加与搜索单词 - 数据结构设计

文章目录

    • 添加与搜索单词 - 数据结构设计
      • 思路一
      • 思路二

添加与搜索单词 - 数据结构设计

请你设计一个数据结构,支持 添加新单词 和 查找字符串是否与任何先前添加的字符串匹配 。
实现词典类 WordDictionary
WordDictionary() 初始化词典对象
void addWord(word)word 添加到数据结构中,之后可以对它进行匹配
bool search(word) 如果数据结构中存在字符串与 word 匹配,则返回 true ;否则,返回 falseword 中可能包含一些 ‘.’ ,每个 . 都可以表示任何一个字母。

输入:
["WordDictionary","addWord","addWord","addWord","search","search","search","search"]
[[],["bad"],["dad"],["mad"],["pad"],["bad"],[".ad"],["b.."]]
输出:
[null,null,null,null,false,true,true,true]解释:
WordDictionary wordDictionary = new WordDictionary();
wordDictionary.addWord("bad");
wordDictionary.addWord("dad");
wordDictionary.addWord("mad");
wordDictionary.search("pad"); // 返回 False
wordDictionary.search("bad"); // 返回 True
wordDictionary.search(".ad"); // 返回 True
wordDictionary.search("b.."); // 返回 True

思路一

var WordDictionary = function() {this.root = {};
};/** * @param {string} word* @return {void}*/
WordDictionary.prototype.addWord = function(word) {let node = this.root;for (let char of word) {if (!node[char]) {node[char] = {};}node = node[char];}node.isWord = true;
};/** * @param {string} word* @return {boolean}*/
WordDictionary.prototype.search = function(word) {return this.dfs(this.root, word, 0);
};WordDictionary.prototype.dfs = function(node, word, index) {const char = word[index];if (index === word.length) {return node.isWord === true;}if (char !== '.') {if (node[char] && this.dfs(node[char], word, index + 1)) {return true;}} else {for (let childChar in node) {if (childChar !== 'isWord' && this.dfs(node[childChar], word, index + 1)) {return true;}}}return false;
};

讲解
WordDictionary 构造函数

  1. 初始化 Trie 结构:WordDictionary构造函数初始化一个空的字典树,根节点是一个空对象{},用于后续插入和搜索操作。

addWord 方法

  1. 遍历单词:遍历给定的单词word的每一个字符char,从根节点开始。
  2. 插入字符到 Trie:对于每一个字符,如果当前节点没有对应的子节点,则创建一个新的子节点。然后,将当前节点更新为这个子节点,继续处理下一个字符。
  3. 标记单词结束:当所有字符都处理完毕后,将最后一个节点的isWord属性设为true,表示一个单词的结束。

search 方法

  1. 调用 DFS 方法:search方法接收一个可能包含通配符.的单词,然后调用dfs方法从根节点开始进行深度优先搜索。
  2. 处理字符:对于每个字符,如果字符不是通配符.,则检查当前节点是否有对应的子节点,如果有,则递归调用dfs继续搜索;如果没有,则返回false
  3. 处理通配符:如果遇到通配符.,则遍历当前节点的所有子节点,递归调用dfs方法进行搜索,如果在任一子节点的搜索中返回true,则立即返回true

dfs 方法

  1. 结束条件:如果当前索引index等于输入单词的长度,说明已经遍历完所有字符,此时如果当前节点的isWord属性为true,则返回true,表示找到匹配的单词。
  2. 非通配符处理:如果当前字符不是通配符.,检查当前节点是否有对应的子节点,如果有,则递归调用dfs方法继续搜索,否则返回false
  3. 通配符处理:如果当前字符是通配符.,遍历当前节点的所有子节点(除了isWord属性),对每个子节点递归调用dfs方法进行搜索,如果在任一子节点的搜索中返回true,则立即返回true

思路二

class TrieNode {constructor() {this.children = {};this.isEndOfWord = false;}
}class WordDictionary {constructor() {this.root = new TrieNode();}// 添加单词addWord(word) {let node = this.root;for (let char of word) {if (!node.children[char]) {node.children[char] = new TrieNode();}node = node.children[char];}node.isEndOfWord = true; // 标记单词的结束}// 搜索单词search(word) {return this._searchInNode(word, this.root);}// 递归搜索函数_searchInNode(word, node) {for (let i = 0; i < word.length; i++) {const char = word[i];if (char === '.') {// 如果是 '.', 遍历所有子节点for (let child in node.children) {if (this._searchInNode(word.slice(i + 1), node.children[child])) {return true;}}return false; // 如果没有匹配的子节点} else {// 如果不是 '.', 直接查找子节点if (!node.children[char]) {return false; // 如果没有这个字符,返回 false}node = node.children[char];}}return node.isEndOfWord; // 返回是否是一个完整单词}
}

讲解
TrieNode 类

  1. children:一个对象,用于存储当前节点的所有子节点。每个子节点的键是字符,值是对应的 TrieNode 实例。
  2. isEndOfWord:一个布尔值,标记当前节点是否是一个完整单词的结束。若为 true,则表示从根节点到该节点的路径形成了一个完整的单词。

WordDictionary 类

  1. constructor():初始化 WordDictionary 类时创建一个根节点 this.root,所有单词都将从这个节点开始构建。

addWord() 方法

  1. 这个方法用于将一个新单词添加到字典中。
  2. 从根节点开始遍历单词的每个字符。
  3. 如果当前字符的子节点不存在,则创建一个新的 TrieNode
  4. 移动到当前字符的子节点,继续处理下一个字符。
  5. 最后,将最后一个节点的 isEndOfWord 属性设置为 true,表示这个节点是一个完整单词的结束。

search() 方法

  1. 这个方法用于查找字典中是否存在与给定字符串匹配的单词。它调用 _searchInNode 方法来执行实际的搜索操作。

_searchInNode() 递归搜索

  1. 这个方法是递归的核心部分,负责在 Trie 中查找与给定字符串匹配的单词。
  2. 遍历 word 的每个字符。
  3. 如果字符是 “ . ”,则需要检查当前节点的所有子节点:
    • 对每个子节点,递归调用 _searchInNode 方法,传入剩余的字符串(从 i + 1 开始)。
    • 如果在任何一个子节点中找到了匹配,返回 true
    • 如果所有子节点都没有找到匹配,返回 false
  4. 如果字符不是 “ . ”,则直接查找当前字符对应的子节点:
    • 如果子节点不存在,返回 false
    • 如果子节点存在,移动到该子节点,继续处理下一个字符。
  5. 最后,检查当前节点的 isEndOfWord 属性,返回它的值,表示是否找到了一个完整的单词。

相关文章:

学习记录:js算法(六十一):添加与搜索单词 - 数据结构设计

文章目录 添加与搜索单词 - 数据结构设计思路一思路二 添加与搜索单词 - 数据结构设计 请你设计一个数据结构&#xff0c;支持 添加新单词 和 查找字符串是否与任何先前添加的字符串匹配 。 实现词典类 WordDictionary &#xff1a; ● WordDictionary() 初始化词典对象 ● voi…...

Jetpack-ObservableField实现双向绑定

ObservableField是Android Data Binding库中的一个类&#xff0c;用于实现双向绑定。双向绑定意味着当数据模型中的数据发生变化时&#xff0c;UI会自动更新&#xff1b;同时&#xff0c;当用户在UI上进行操作时&#xff0c;数据模型也会相应地更新。 1.在你的项目中添加Data …...

STARnak, LTR 模型笔记

未完成. 1. 简述 CIKM 23 的一篇论文, 任务为 Learning To Rank, 输入为 候选集合, 输出为 有序列表, 用于 top-n 推荐场景. 思考: 它是要替代 ctr 预估么?它跟 mind 这种召回, 有啥大的不一样么? 2. 网络结构 u u u: 将用户(或 query) 记为 u H q d X , d Y , . . . H…...

【数据结构】:破译排序算法--数字世界的秩序密码(二)

文章目录 前言一.比较排序算法1.Bubble Sort冒泡排序1.1.冒泡排序原理1.2.冒泡排序过程1.3.代码实现1.4.复杂度和稳定性 2.Quick Sort快速排序2.1递归快速排序2.1.1.递归快速排序原理2.1.2.递归快速排序过程2.1.3.代码实现 2.2.非递归快速排序2.2.1.非递归快速排序原理2.2.2.非…...

2024年《生成式ai大模型》都学什么内容呢?

近期大家都在关注的2024 2024年10月25日 — 2024年10月29日 在成都举办的第八期《新质技术之生成式AI、大模型、多模态技术开发与应用研修班》都学什么内容呢&#xff1f;下面我们来看看&#xff1a; 1.了解AIGC发展现状与核心技术。 2.掌握Transformer核心开发技术。 3.掌握…...

kubernetes自定义pod启动用户

一、kubernetes自定义pod启动用户 一&#xff09;以root用户启动pod containers:- name: ...image: ...securityContext:runAsUser: 0 二&#xff09;以普通用户启动pod 1、从构建镜像角度修改 # RUN命令执行创建用户和用户组&#xff08;命令创建了一个用户newuser设定ID为1…...

C4T避风型电动采光排烟天窗(图集09J621-2)

C4T避风型电动采光排烟天窗是09J621-2《电动采光排烟天窗》图集中的一种窗型。也是一种现代化的建筑消防排烟通风采光设备&#xff0c;被广泛应用于多风地区厂房。 C4T避风型电动采光排烟天窗配有成品避风罩&#xff0c;该避风置由钢制骨架和彩色钢板构成&#xff0c;固定在电动…...

多态常见面试问题

1、什么是多态&#xff1f; 多态&#xff08;Polymorphism&#xff09;是面向对象编程中的一个重要概念&#xff0c;它允许同一个接口表现出不同的行为。在C中&#xff0c;多态性主要通过虚函数来实现&#xff0c;分为编译时多态&#xff08;静态多态&#xff09;和运行时多态…...

案例-登录认证(上)

案例-登录认证 在前面的课程中&#xff0c;我们已经实现了部门管理、员工管理的基本功能&#xff0c;但是大家会发现&#xff0c;我们并没有登 录&#xff0c;就直接访问到了Tlias智能学习辅助系统的后台。 这是不安全的&#xff0c;所以我们今天的主题就是登录 认证。 最终我…...

对BSV区块链下一代节点Teranode的答疑解惑(上篇)

​​发表时间&#xff1a;2024年8月7日 2024年初BSV区块链研发团队揭晓了即将到来的Teranode更新的突破性特性&#xff0c;这些特性将显著提升网络的效率和处理速度&#xff0c;使BSV区块链能够达到百万级TPS。 Teranode的项目主管Siggi Oskarsson强调&#xff1a;“当你阅读这…...

vue父子组件传参的方法

在Vue.js中&#xff0c;父子组件之间的参数传递是常见的需求。Vue提供了几种方法来实现这一点&#xff0c;主要包括使用props传递数据给子组件&#xff0c;以及使用事件&#xff08;如自定义事件&#xff09;从子组件向父组件发送数据。以下是详细的说明&#xff1a; 父组件向…...

关于this指针

在普通成员函数里 1.this指针不能显式说明&#xff0c;但能显示使用&#xff0c;是个常指针&#xff0c;只能改变指针指向的对象的内容&#xff0c;不能改变指针存储的对象的地址。 2.this指针一般不用特别写上&#xff0c;只有在&#xff08;我目前的知识范围内&#xff09;类…...

机器学习西瓜书

绪论 1.1绪论1.2课程定位 科学:是什么,为什么; 技术:怎么做; 工程:做的多快好省; 应用: 1.3机器学习 经典定义:利用经验改善系统自身的性能 1.4典型的机器学习过程 1.5计算学习理论 机器学习有坚实的理论基础,由Leslie Valiant的计算学习理论现在有一个数据样本x,现在…...

如何使用 Puppeteer 和 Browserless 运行自动化测试?

Puppeteer&#xff1a;什么是 Puppeteer 及其功能 Puppeteer 是一个 Node.js 库。使用 Puppeteer&#xff0c;您可以在所有基于 Chromium 的浏览器上测试您的网站&#xff0c;包括 Chrome、Microsoft Edge Chrome 和 Chromium。此外&#xff0c;Puppeteer 可用于网页抓取、自动…...

python菜鸟知识

去除空格 str 这是 含 空格 print(f去除两端空格{str.strip()}) print(f去除左端空格{str.lstrip()}) print(f去除右端空格{str.rstrip()}) print(f去除全部空格{str.replace(" ", "")}) 方法返回对象yield yield :.join([ip, port])yield {ranking…...

GPT4o,GPTo1-preview, 拼

兄弟们GPT刚开的 需要上车的扣&#xff0c;工作用 大家一起PIN分摊点压力。 在当今数字化的时代&#xff0c;程序员这一职业已经从幕后走到了前台&#xff0c;成为推动科技进步和社会变革的关键力量。编写代码、解决问题、不断学习新技术&#xff0c;程序员们的日常充满了挑战与…...

论文笔记:Pre-training to Match for Unified Low-shot Relation Extraction

论文来源&#xff1a;ACL 2022 论文地址&#xff1a;https://aclanthology.org/2022.acl-long.397.pdf 论文代码&#xff1a;https://github.com/fc-liu/MCMN &#xff08;笔记不易&#xff0c;请勿恶意转载抄袭&#xff01;&#xff01;&#xff01;&#xff09; 目录 A…...

一篇文章带你快速了解linux中关于信号的核心内容

1. 信号概念 信号是操作系统用来通知进程某个特定事件已经发生的一种方式。它们是一种软件中断&#xff0c;可以被发送到进程以对其进行异步通知。 2. 信号处理的三种方式 执行默认动作执行自定义动作忽略 signal() 函数&#xff1a;将信号处理设置为 SIG_IGN&#xff0c;可…...

openEuler、Linux操作系统常见操作-(6)如何登录Linux

如何登录Linux Linux登陆方式主要有如下两种: 。本地登陆 。一个典型的Linux系统将运行六个虚拟控制台和一个图形控制台&#xff0c;openEuler目前暂未支持图形化界面; 可以通过CtrlAltF[1-6]在6个虚拟控制台之间进行切换。 远程登录 。默认情况下openEuler支持远程登录&…...

Python基础语法条件

注释 注释的作用 通过用自己熟悉的语言&#xff0c;在程序中对某些代码进行标注说明&#xff0c;这就是注释的作用&#xff0c;能够大大增强程序的可读性。 注释的分类及语法 注释分为两类&#xff1a;单行注释 和 多行注释。 单行注释 只能注释一行内容&#xff0c;语法如下…...

模型参数、模型存储精度、参数与显存

模型参数量衡量单位 M&#xff1a;百万&#xff08;Million&#xff09; B&#xff1a;十亿&#xff08;Billion&#xff09; 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的&#xff0c;但是一个参数所表示多少字节不一定&#xff0c;需要看这个参数以什么…...

uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖

在前面的练习中&#xff0c;每个页面需要使用ref&#xff0c;onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入&#xff0c;需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...

【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】

1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件&#xff08;System Property Definition File&#xff09;&#xff0c;用于声明和管理 Bluetooth 模块相…...

Linux-07 ubuntu 的 chrome 启动不了

文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了&#xff0c;报错如下四、启动不了&#xff0c;解决如下 总结 问题原因 在应用中可以看到chrome&#xff0c;但是打不开(说明&#xff1a;原来的ubuntu系统出问题了&#xff0c;这个是备用的硬盘&a…...

Python如何给视频添加音频和字幕

在Python中&#xff0c;给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加&#xff0c;包括必要的代码示例和详细解释。 环境准备 在开始之前&#xff0c;需要安装以下Python库&#xff1a;…...

自然语言处理——Transformer

自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效&#xff0c;它能挖掘数据中的时序信息以及语义信息&#xff0c;但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN&#xff0c;但是…...

汇编常见指令

汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX&#xff08;不访问内存&#xff09;XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计

随着大语言模型&#xff08;LLM&#xff09;参数规模的增长&#xff0c;推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长&#xff0c;而KV缓存的内存消耗可能高达数十GB&#xff08;例如Llama2-7B处理100K token时需50GB内存&a…...

【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)

本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...

Java数值运算常见陷阱与规避方法

整数除法中的舍入问题 问题现象 当开发者预期进行浮点除法却误用整数除法时,会出现小数部分被截断的情况。典型错误模式如下: void process(int value) {double half = value / 2; // 整数除法导致截断// 使用half变量 }此时...