leetcode 648. 单词替换【python3哈希集与两种字典树的方法的思考过程整理】

news2024/11/26 12:22:04

题目

在英语中,我们有一个叫做 词根(root) 的概念,可以词根后面添加其他一些词组成另一个较长的单词——我们称这个词为 继承词(successor)。例如,词根an,跟随着单词 other(其他),可以形成新的单词 another(另一个)。
现在,给定一个由许多词根组成的词典 dictionary 和一个用空格分隔单词形成的句子 sentence。你需要将句子中的所有继承词用词根替换掉。如果继承词有许多可以形成它的词根,则用最短的词根替换它。
你需要输出替换之后的句子。

示例 1:

  • 输入:dictionary = [“cat”,“bat”,“rat”], sentence = “the cattle was rattled by the battery”
  • 输出:“the cat was rat by the bat”

题解

方法1 哈希

该题目写的太晦涩,其实题意很简单,就是对sentence中的每个单词在dictionary中找最短的前缀,如果有就替换,没有不替换。暴力点的做法就是把sentence中的单词逐个的匹配dictionary中的单词,找出最短的前缀。为了加速,比较容易想到的就是用哈希,这里可以对dictionary用哈希集合,也可以用hash表,测试了下hash即可的效率高一些。接下来面临的问题就是如果一个单词匹配多个前缀需要选择最短的一个。这个就通过对word从左遍历,最选匹配到的就是最短的。直接写代码如下:

class Solution:
    def replaceWords(self, dictionary: List[str], sentence: str) -> str:
        dictionarySet = set(dictionary)
        word_list=sentence.split()
        for i, word in enumerate(word_list):
            for j in range(1, len(word) + 1):
                if word[:j] in dictionarySet:
                    word_list[i] = word[:j]
                    break
        return ' '.join(word_list)

计算复杂度

  • 时间复杂度。假设d是dictionary的字符数,构建哈希结合的时间复杂度为 O ( d ) O(d) O(d),假设sentence中一共有m个单词,每个单词的长度为n,则每个单词的前缀是否属于hash即可的判断时间复杂度为 O ( n 2 ) O(n^2) O(n2),因此,整个时间复杂度为 O ( d + m ∗ n 2 ) O(d+m*n^2) O(d+mn2)
  • 空间复杂度。哈希集合的占用空间为 O ( d ) O(d) O(d),分割setence占用空间为 O ( n ) O(n) O(n),整体的空间复杂度为 O ( d + n ) O(d+n) O(d+n)

方法2 字典树

这道题目首先想到的就是字典树。利用哈希表的方法是在看到官方题解才想到的,因为使用哈希表也存在大量的重复比较。因此字典树才是这道题目的核心考核点。首先,需要根据dictionary构建字典树,因此字典树的类需要一个构建功能。其次需要一个搜索字符的功能,这个功能与典型的字典树稍微有区别,这里只需要匹配到最短的一个树,而不需要匹配完整个字符串,在找最短前缀字典树占优势,碰到第一个终止的字符时结束返回这个字符串即可。为了方便可以增加一个prefix变量用来存储每个字典树的根节点到结束字符之间的字符串,这个字符串就是搜索字符串的前缀,方便直接输出结果。
以示例1为例给出字典树的数据结构图:
image.png

字典树的构建跟典型字典树差别不大,只需增加一个prefix变量即可。而搜索需要有所修改,在碰到第一个isEnd为True有节点也就是橘黄色节点时,需要返回该节点prefix节点值,如果没有匹配上返回空。
代码:

class Trie:
    def __init__(self):
        self.children=[None]*26
        self.isEnd=False
        self.prefix=None


    def insert(self,word):
        node=self
        for ch in word:
            num=ord(ch)-ord("a")
            if not node.children[num]:
                #创建节点
                node.children[num]=Trie()
            node=node.children[num]
        node.isEnd=True
        node.prefix=word

    
    #搜索最短前缀
    def prefix_search(self,word):
        node=self
        for ch in word:
            num=ord(ch)-ord("a")
            if node.children[num]:
                if node.children[num].isEnd:
                    return node.children[num].prefix
                node=node.children[num]
            else:
                return ''
            
class Solution:
    def replaceWords(self, dictionary: List[str], sentence: str) -> str:
        dict_tree=Trie()
        #建立词根的字典序
        for word in dictionary:
            dict_tree.insert(word)
        sen_list=sentence.split()
        for i in range(len(sen_list)):
            if dict_tree.prefix_search(sen_list[i]):
                sen_list[i]=dict_tree.prefix_search(sen_list[i])
        return ' '.join(sen_list)

官方代码理解

官方代码更简介一些,主要是采用了嵌套dict来实现字典树。示例1中的dictionary构建的字典树如下图所示:
image.png

官方代码如下:

class Solution:
    def replaceWords(self, dictionary: List[str], sentence: str) -> str:
        #利用嵌套字典构建字典树
        trie = {}
        for word in dictionary:
            cur = trie
            for c in word:
                if c not in cur:
                    cur[c] = {}
                cur = cur[c]
            # #号作为一个word的终止符
            cur['#'] = {}

        words = sentence.split(' ')
        for i, word in enumerate(words):
            cur = trie
            for j, c in enumerate(word):
                #碰到的第一个终止符直接替换,跳出循环,因为第一个是最小前缀
                if '#' in cur:
                    words[i] = word[:j]
                    break
                if c not in cur:
                    break
                cur = cur[c]
        return ' '.join(words)

整体来说如果对字典树比较熟悉,通过第一种方法构建字典树这种方法虽然代码长,但是思路比较清晰。第二种构建字典树的方法简洁,很有技巧性。

计算复杂度

  • 时间复杂度。构建字典树消耗 O ( d ) O(d) O(d) 时间,字典数的搜索的复杂度为 O ( 1 ) O(1) O(1),因此整体的时间复度为 O ( d ) O(d) O(d)
  • 空间复杂度。哈希集合的占用空间为 O ( d ) O(d) O(d),分割setence占用空间为 O ( n ) O(n) O(n),整体的空间复杂度为 O ( d + n ) O(d+n) O(d+n)

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

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

相关文章

UI自动化测试模块与环境管理全面打通,MeterSphere开源持续测试平台v2.6.0发布

2023年1月16日,MeterSphere一站式开源持续测试平台正式发布v2.6.0版本。 在这一版本中,MeterSphere的UI自动化测试模块与环境管理全面打通,更好地满足了用户一个脚本同时跑多个环境的测试需求。在测试跟踪模块中,测试计划关联测试…

怎么系统的阅读文献

文章目录一、文献阅读1、综述类文献 review article2、研究类文章 research article3、方法学的文章第一部分 综述类文章的阅读第二部分 研究型文章的阅读a. 研究型论文结构b. 如何有选择阅读文献c. 如果整理笔记Citation和Reference的区别二、文献阅读工具1、Connected Papers…

python-while循环

文章目录一、程序的三种结构二、while循环1.1:死循环1.2:循环计数习惯案例1.3:循环计数2.0:break终止循环3.0:人造死循环4.0:continue5.0循环嵌套一、程序的三种结构 1:顺序 代码自上而下执行 …

四旋翼无人机学习第20节--PCB自动保存文件labview设计

0 前言 在设计PCB的过程中,通常一个项目的的PCB文件只有一个,如果保存完文件后想要回滚到自己的版本是比较难的,虽然allergo软件可以设置autosave功能来自动对PCB文件进行备份,但是备份文件只会保存最后一次的版本。 1 labview编…

JavaWeb基础(二) HTTP、Tomcat、Servlet介绍

JavaWeb基础(二) HTTP、Tomcat、Servlet介绍 1,Web概述 1.1 Web和JavaWeb的概念 Web是全球广域网,也称为万维网(www),能够通过浏览器访问的网站。 在我们日常的生活中,经常会使用浏览器去访问百度、京东、传智官网等这些网站&a…

Dubbo调用

Dubbo调用 0. 概述 Dubbo 服务调用过程比较复杂,包含众多步骤,比如发送请求、编解码、服务降级、过滤器链处理、序列化、线程派发以及响应请求等步骤。 1. 客户端发送请求时序图 InvokerInvocationHandler.invoke 1. 对于Object中的方法toString, has…

IDEA常用配置整理说明

文章目录IDEA常用配置整理说明1、 IDE配置1.1 设置相关1.1.1 忽略大小写开关1.1.2 取消单行显示tabs的操作1.1.3 项目文件编码1.1.4 滚轴修改字体大小1.1.5 设置显示行号和方法间的分隔符1.1.6 新建类头注释信息1.1.7 JavaDoc注释(就是方法上加的注释)1.…

蓝桥杯:整数分解

题目链接 问题描述 答案提交 本题答案:691677274345。 思路分析 问题描述 将 3 分解成两个正整数的和, 有两种分解方法, 分别是312 和 321 。注意顺序不同算不同的方法。 将 5 分解成三个正整数的和, 有 6 种分解方法, 它们是 113 122 131 212 221 311。…

WebSocket长连接接入支付宝消息服务,实现消息通知

大家好,我是小悟 在对接支付宝开放平台的一些常用功能时,常常需要收到支付宝的回调通知结果,才能处理业务逻辑。此文介绍通过WebSocket长连接接入支付宝消息服务,实现消息通知。 包括五部分内容:问题、优势、配置、代…

Spring3.*中ASM和JDK8版本冲突问题及解决方案

1. 问题描述 Spring3.* 中ASM版本较低,不支持对 JDK8 class文件进行操作,启动时报错。 Tomcat报错 org.springframework.asm.MethodVisitor.visitParameter2. 问题原因 Spring使用ASM类库操作Java class文件,Spring.* 依赖的ASM类库版本比…

右键万能格式转换工具

格式转换是很多小伙伴都会用到的东西,无论是视频、音频还是文档等格式,其实做这方面的软件有很多,比如之前一直在用的格式工厂,蛮好用的。后面用到了ABC工具箱,(这款软件批量处理图片会很方面)界…

故障分析 | 库表名-大小写不规范,运维两行泪

作者:刘聪 爱可生华东交付服务部 DBA 成员,专职 MySQL 故障处理及相关技术支持。座右铭:好好学习,天天向上。 本文来源:原创投稿 *爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系…

【博客589】K8s Topology Spread Constraints

K8s Topology Spread Constraints 场景 你可以使用 拓扑分布约束(Topology Spread Constraints) 来控制 Pod 在集群内故障域之间的分布, 例如区域(Region)、可用区(Zone)、节点和其他用户自定义…

带你从概念到服务对象,解读商业智能BI

数据在当前时代已然成为了重要的战略资源,但数据资产却并不是每个企业都能利用。数据本身并没有太多意义,规模小还好,一旦规模量变大,人们就难以理解其中的含义。所以讲数据资产价值化,使其转化为信息和知识成为了企业…

五个了解自己天赋优势的分析工具(四)MBTI测试

MBTI测试 MBTI全称“迈尔斯-布⾥格斯类型指标”,是美国作家伊莎⻉尔布⾥格斯迈尔斯和她的⺟亲凯瑟琳库克布⾥格斯在20世纪40年代编制的⼀种⼈格测试。 这⼀测试的基础来⾃著名⼼理学家荣格提出的⼼理类型理论。 荣格将⼈的性格类型分为“内向(I&#xf…

广告业务系统 之 业务串联 —— “ PDB - 广告投放【保量保价】”

文章目录广告业务系统 之 业务串联 —— “ PDB - 广告投放【保量保价】”PDB - 广告投放[保量保价]PDB 浅述PDB 数据流图保量逻辑设计订单曝光拆分凌晨停量补量广告业务系统 之 业务串联 —— “ PDB - 广告投放【保量保价】” PDB - 广告投放[保量保价] 常规的 ADX 系统&am…

【C语言练习】 二进制中1的个数

目录题目详情:思路一:思路二:思路三:题目详情: 思路一: 拿到二进制的每一位,看它是否等于 111,再定义一个计数器变量,如果等于 111,计数器变量就加 111。最终…

rancher的k3s证书过期

文章目录现象rancher报错日志分析解决思路解决现象 web上rancher不能访问,服务上看443端口没了,6443端口仍然在。 rancher报错日志 rancher | time"2023-01-05T01:56:07.241615176Z" levelinfo msg"Waiting for master node start…

代码随想录--数组相关题目整理

LeetCode数组相关题目整理 1. LeetCode704 二分查找 给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。 解题思路&#xf…

亚马逊云科技助力游戏上云学习心得-运行篇

云服务已经是大势所趋了,通过购置传统服务器来进行应用开发,无法与现代化敏捷的开发方法相结合,对于系统运维的难度也大大增加,而云服务的弹性伸缩、动态计费可以很好地帮助中小企业实现快速应用开发,使得产品的价值最…