LeetCode 2707. Extra Characters in a String【动态规划,记忆化搜索,Trie】1735
本文属于「征服LeetCode」系列文章之一,这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁,本系列将至少持续到刷完所有无锁题之日为止;由于LeetCode还在不断地创建新题,本系列的终止日期可能是永远。在这一系列刷题文章中,我不仅会讲解多种解题思路及其优化,还会用多种编程语言实现题解,涉及到通用解法时更将归纳总结出相应的算法模板。
为了方便在PC上运行调试、分享代码文件,我还建立了相关的仓库:https://github.com/memcpy0/LeetCode-Conquest。在这一仓库中,你不仅可以看到LeetCode原题链接、题解代码、题解文章链接、同类题目归纳、通用解法总结等,还可以看到原题出现频率和相关企业等重要信息。如果有其他优选题解,还可以一同分享给他人。
由于本系列文章的内容随时可能发生更新变动,欢迎关注和收藏征服LeetCode系列文章目录一文以作备忘。
给你一个下标从 0 开始的字符串 s 和一个单词字典 dictionary 。你需要将 s 分割成若干个 互不重叠 的子字符串,每个子字符串都在 dictionary 中出现过。s 中可能会有一些 额外的字符 不在任何子字符串中。
请你采取最优策略分割 s ,使剩下的字符 最少 。
示例 1:
输入:s = "leetscode", dictionary = ["leet","code","leetcode"]
输出:1
解释:将 s 分成两个子字符串:下标从 0 到 3 的 "leet" 和下标从 5 到 8 的 "code" 。只有 1 个字符没有使用(下标为 4),所以我们返回 1 。
示例 2:
输入:s = "sayhelloworld", dictionary = ["hello","world"]
输出:3
解释:将 s 分成两个子字符串:下标从 3 到 7 的 "hello" 和下标从 8 到 12 的 "world" 。下标为 0 ,1 和 2 的字符没有使用,所以我们返回 3 。
提示:
1 <= s.length <= 501 <= dictionary.length <= 501 <= dictionary[i].length <= 50dictionary[i]和s只包含小写英文字母。dictionary中的单词互不相同。
我们有一个字符串 s s s 和一个 d i c t i o n a r y dictionary dictionary 。目标是将 s s s 分解为一个或多个不重叠的子字符串,每个子字符串都出现在 d i c t i o n a r y dictionary dictionary 中,并最大限度地减少剩余的额外字符数。
我们可以使用动态规划来解决这个问题。有两种常见的方法:自下而上(迭代)和自上而下(带记忆的递归)。这两种方法都旨在找到最少额外字符数(从字符串末尾遍历到开头)。
初始化:初始化一个 d p dp dp 数组,在字符串 s s s 的每个位置存储最少额外字符数。先要将 d p dp dp 中所有元素初始化为一个最大值(例如, − 1 -1 −1 或一个大数字),表示它们还没有被计算出来。
解法1 记忆化搜索——自上而下方法
设 n n n 为 s s s 的长度,我们可以定义一个递归函数 d f s ( i ) dfs(i) dfs(i) ,该函数从字符串 s [ i ] s[i] s[i] 开始计算最少额外字符数。并使用数组 d p dp dp 来存储中间结果,以避免重复计算;将 d p dp dp 中的所有元素初始化为一个特殊值(例如 − 1 -1 −1 ),表示它们还没有计算出来。
在递归函数中,如果 d p [ i ] dp[i] dp[i] 已经算出则直接返回;如果尚未计算(等于 − 1 -1 −1 ),则按如下方式计算:
- 初始化 d p [ i ] dp[i] dp[i] ,值为 1 + d f s ( s , i + 1 ) 1+dfs(s, i+1) 1+dfs(s,i+1) ,表示在当前字符处断开字符串,并将当前字符 s [ i ] s[i] s[i] 作为额外字符,在下一位置找到的最少额外字符数中添加这个额外字符。即直接跳过当前字符 s [ i ] s[i] s[i] ,让问题变为 s s s 的后面 n − i − 1 n - i - 1 n−i−1 个字符的子问题。
- 检查 d i c t i o i n a r y dictioinary dictioinary 中的每个单词,是否与「从当前位置 i i i 开始的子串」匹配。如果找到匹配,则将 d p [ i ] dp[i] dp[i] 更新为其当前值和 1 + d f s ( s , i + w . s i z e ( ) ) 1+dfs(s, i+w.size()) 1+dfs(s,i+w.size()) 之间的最小值,其中 w . s i z e ( ) w.size() w.size() 是匹配单词的长度。
最后返回 d p [ 0 ] dp[0] dp[0] ,它表示从位置 0 0 0 开始的最小额外字符数。
class Solution {
public:int n;vector<int> dp;int dfs(string &s, vector<string>& d, int i) {if (i >= n) return 0;if (dp[i] != -1) return dp[i]; // 已经计算了dp[i] = 1 + dfs(s, d, i + 1);for (string& w : d) if (i + w.size() <= n && s.compare(i, w.size(), w) == 0)dp[i] = min(dp[i], dfs(s, d, i + w.size()));return dp[i];}int minExtraChar(string s, vector<string>& dictionary) {n = s.size();dp.resize(n, -1);return dfs(s, dictionary, 0);}
};
解法2 动态规划——自下而上(迭代)
开始从末尾(从右到左)遍历字符串 s s s 。
- 对于每个位置 i i i ,使用值 1 + d p [ i + 1 ] 1+dp[i+1] 1+dp[i+1] 初始化 d p [ i ] dp[i] dp[i] 。这表示在当前字符处断开字符串,并将当前字符 s [ i ] s[i] s[i] 作为额外字符,在下一位置找到的最少额外字符数中添加这个额外字符 adding one extra character to the minimum extra characters found in the next position 。
- 然后检查 d i c t i o n a r y dictionary dictionary 中的每个单词,是否与「从当前位置 i i i 开始的子串」匹配,即不把 s [ i ] s[i] s[i] 作为额外字符去除。如果找到匹配,将 d p [ i ] dp[i] dp[i] 更新为其当前值与 d p [ i + w . s i z e ( ) ] dp[i+w.size()] dp[i+w.size()] 两者间最小值,其中 w . s i z e ( ) w.size() w.size() 是匹配单词的长度。
- 对字符串 s s s 中的所有位置继续此过程, d p [ 0 ] dp[0] dp[0] 的最终值将表示剩余的最小额外字符数。
class Solution {
public:int minExtraChar(string s, vector<string>& dictionary) {int n = s.size();vector<int> dp(n + 1);// dp[i]表示从s[i:n)中分割剩下的最少字符数for (int i = n - 1; i >= 0; --i) {dp[i] = dp[i + 1] + 1;for (string& w : dictionary) if (i + w.size() <= n && s.compare(i, w.size(), w) == 0)dp[i] = min(dp[i], dp[i + w.size()]);}return dp[0];}
};
复杂度分析:
- 时间复杂度: O ( n m L ) O(nmL) O(nmL) ,其中 n n n 为 s s s 的长度, m m m 为 d i c t i o n a r y dictionary dictionary 的长度, L L L 为 dictionary \textit{dictionary} dictionary 所有字符串的长度之和。动态规划的时间复杂度 = 状态个数 × \times × 单个状态的计算时间。本题中状态个数等于 O ( n ) O(n) O(n) ,单个状态的计算时间为 O ( m L ) O(mL) O(mL) 。
- 空间复杂度: O ( n ) O(n) O(n) 。
相关文章:
LeetCode 2707. Extra Characters in a String【动态规划,记忆化搜索,Trie】1735
本文属于「征服LeetCode」系列文章之一,这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁,本系列将至少持续到刷完所有无锁题之日为止;由于LeetCode还在不断地创建新题,本系列的终止日期可能是永远。在这一系列刷题文章…...
设计模式行为型-模板模式
文章目录 一:模板方法设计模式概述1.1 简介1.2 定义和目的1.3 关键特点1.4 适用场景 二:模板方法设计模式基本原理2.1 抽象类2.1.1 定义和作用2.1.2 模板方法2.1.3 具体方法 2.2 具体类2.2.1 定义和作用2.2.2 实现抽象类中的抽象方法2.2.3 覆盖钩子方法 …...
9.3.tensorRT高级(4)封装系列-自动驾驶案例项目self-driving-车道线检测
目录 前言1. 车道线检测总结 前言 杜老师推出的 tensorRT从零起步高性能部署 课程,之前有看过一遍,但是没有做笔记,很多东西也忘了。这次重新撸一遍,顺便记记笔记。 本次课程学习 tensorRT 高级-自动驾驶案例项目self-driving-车道…...
django.core.exceptions.AppRegistryNotReady: Apps aren‘t loaded yet.
运行django测试用例报错django.core.exceptions.AppRegistryNotReady: Apps arent loaded yet. 解决:在测试文件上方加上 django.setup() django.setup()是Django框架中的一个函数。它用于在非Django环境下使用Django的各种功能、模型和设置。 在常规的Django应用…...
【C#】C#调用进程打开一个exe程序
文章目录 一、过程二、效果总结 一、过程 新建WinForm程序,并写入代码,明确要调用的程序的绝对路径(或相对路径)下的exe文件。 调用代码: 这里我调用的另一个程序的路径是: F:\WindowsFormsApplication2…...
宝塔面板定时监控和重启MySQL数据库(计划任务)
往期教程 如果还有不了解宝塔面板怎么使用的小伙伴,可以看下我总结的系列教程,保证从新手变老鸟: 【建站流程科普】 个人和企业搭建网站基本流程及六个主要步骤常见的VPS主机运维面板汇总—网站运维面板云服务器,VPS࿰…...
Beats:安装及配置 Metricbeat (二)- 8.x
这篇文章是继文章 “Beats:安装及配置 Metricbeat (一)- 8.x” 的续篇。你可以先阅读之前的那篇文章再继续阅读这篇文章。我们在这篇文章中继续之前的探讨。 使用 fingerprint 来代替证书 在实际的使用中,我们需要从 Elasticsear…...
Redis之哨兵模式解读
目录 基本介绍 单哨兵模式 多哨兵模式 哨兵的本质 配置哨兵模式 故障恢复原理 哨兵监控工作流程 哨兵模式缺点 基本介绍 当主服务器宕机后,需要手动把一台从服务器切换为主服务器,这就需要人工干预,费事费力,还会造成一段时间内服务不可用。这不是一种推荐的方式,更多…...
题目:2644.找出可整除性得分最大的整数
题目来源: leetcode题目,网址:2644. 找出可整除性得分最大的整数 - 力扣(LeetCode) 解题思路: 遍历计算即可。 解题代码: class Solution {public int maxDivScore(int[] nums, int[] di…...
报错:axios 发送的接口请求 404
axios 发送的接口请求 404 一、问题二、分析 一、问题 二、分析 axios 发送的接口请求 404,根本没有把接口信息发送到后端,这个时候你可以查看检查一下自己的接口名字,或让后端配合换一个接口名字再发送一次接口请求...
三年前端还不会配置Nginx?刷完这篇就够了
什么是Nginx Nginx是一个开源的高性能HTTP和反向代理服务器。它可以用于处理静态资源、负载均衡、反向代理和缓存等任务。Nginx被广泛用于构建高可用性、高性能的Web应用程序和网站。它具有低内存消耗、高并发能力和良好的稳定性,因此在互联网领域非常受欢迎。 为…...
blender 场景灯光基础设置
在 blender 中,打光分为两个部分,一个是世界光,一个是场景光; 世界光: 世界光:在 Blender 中,世界光指的是用于设置场景整体照明的环境光。它可以通过调整颜色、强度、阴影等参数来影响场景的…...
如何查看 SQLyog 中数据库连接信息中的密码
SQLyog 数据库连接信息中的密码无法选择明文展示,也无法复制 可以将数据库连接信息导出到文本查看明文密码 工具--》导入/导出连接详情:...
【SpringSecurity】八、集成图片验证码
文章目录 1、生成图片验证码2、创建验证码过滤器3、将过滤器加入SpringSecurity过滤链4、修改登录页 SpringSecurity是通过过滤器链来完成的,接下来的验证码,可以尝试创建一个过滤器放到Security的过滤器链中,在自定义的过滤器中比较验证码。…...
【本地代码问题】启动程序,报错:java.lang.IllegalArgumentException: No selectors
启动程序的时候报错了 问题怎么出现的解决方式,注释掉jetty的内容,回归tomcat的使用 问题怎么出现的 我本地启动程序的时候报错了:报的是这个错误,可能和容器的选择有关吧 解决方式,注释掉jetty的内容,回…...
手写RPC框架--4.服务注册
RPC框架-Gitee代码(麻烦点个Starred, 支持一下吧) RPC框架-GitHub代码(麻烦点个Starred, 支持一下吧) 服务注册 服务注册a.添加服务节点和主机节点b.抽象注册中心c.本地服务列表 服务注册 a.添加服务节点和主机节点 主要完成服务注册和发现的功能,其具体流程如下&…...
oracle 解锁表
操作的前提 用 sys 用户 以 SYSDBA 角色登录 第一种解锁方式 1.查询被锁的表 select object_name,machine,s.sid,s.serial# from v$locked_object l,dba_objects o ,v$session s where l.object_id o.object_id and l.session_ids.sid;2.查询那个session引起表被锁 sele…...
使用Dbeaver连接GaussDB
1.下载DBeaver,官网地址 2.安装软件,打开软件,点击数据库->驱动管理器,具体操作如下图: 3、选择新建后进行参数设置,如下图: 具体参数如下图 驱动名称: GS #随便定义 驱动类型&#…...
WSL使用技巧 / 虚拟机对比
WSL使用技巧 / 虚拟机对比 前言虚拟机比较VMware使用技巧WSL使用技巧官方文档工具安装WSL基本命令运行命令关闭卸载磁盘管理导入导出指定安装路径 前言 本文介绍了VMware和WSL的区别,并详细介绍了WSL的使用方法和技巧。 虚拟机比较 VMware 比较灵活,拥…...
vuex_cart案例
json-server使用 在目录下新建db文件夹>里面新建index.json index.json {"cart": [{"id": 100001,"name": "低帮城市休闲户外鞋天然牛皮COOLMAX纤维","price": 128,"count": 6,"thumb": "http…...
别让严谨变成AI味!实测5大主流降AI工具,这款能完美保留原格式
最近看了一些行业报告,AI工具在写作方面的普及率真的已经超乎想象了。 很多大学生在写论文时也都习惯用AI来辅助寻找灵感、提高效率。 与此同时,相关部门针对人工智能写作出台了一系列规定,各大学术检测平台也都在不断升级AIGC检测算法。 现…...
工业作业火花识别 工业作业安全监测 工业安全火灾识别 火灾烟雾识别
火灾、烟雾及火花检测数据集 数据集概述 本数据集面向计算机视觉目标检测场景构建,聚焦火情风险要素识别,为烟火火花类智能监测模型训练提供标准化图像数据支撑,整体适配深度学习目标检测算法训练、验证与测试流程,可有效支撑安防…...
PostgreSQL 13.8 子查询优化实战:手把手教你读懂 `pull_up_sublinks` 源码
PostgreSQL 13.8 子查询优化实战:手把手教你读懂 pull_up_sublinks 源码 数据库查询优化器是数据库系统的核心组件之一,它负责将用户提交的SQL语句转换为高效的执行计划。在PostgreSQL中,子查询优化是查询优化的重要环节,而pull_u…...
Creo二次开发避坑:用ProAsmcomppathInit搞定装配体遍历,别再卡在ProFeature转ProAsmcomppath了
Creo二次开发实战:高效构建装配体遍历路径的深度解析 在Creo二次开发领域,装配体遍历是许多高级功能的基础操作,但开发者常常会在ProFeature到ProAsmcomppath的转换过程中遭遇瓶颈。本文将从底层数据结构入手,揭示一种被多数文档忽…...
工业自动化实战:Modbus转Profinet网关配置与机器人PLC通信集成
1. 项目概述与核心需求解析最近在做一个产线自动化升级的项目,客户现场有一套六轴关节机器人,控制器是国产的ES-R6系列,需要和产线主控的西门子S7-1200 PLC进行实时数据交互。机器人负责上下料和精密装配,PLC则统筹整条线的启停、…...
京东购物自动化评价:3步解放双手的Python智能助手
京东购物自动化评价:3步解放双手的Python智能助手 【免费下载链接】jd_AutoComment 自动评价,仅供交流学习之用 项目地址: https://gitcode.com/gh_mirrors/jd/jd_AutoComment 还在为京东购物后堆积如山的待评价订单烦恼吗?每次大促后面对几十个商…...
CodeBlocks 20.03 安装与汉化保姆级教程(附中文包下载与常见问题解决)
CodeBlocks 20.03 安装与汉化全流程实战指南 对于刚接触C/C开发的初学者来说,选择一款合适的集成开发环境(IDE)是迈入编程世界的第一步。CodeBlocks以其轻量级、跨平台和开源免费的特性,成为众多教育机构和自学者的首选。本文将带你从零开始,…...
财务RPA只能自动执行吗?它还能结合大模型,进化成财务分析助手
提到财务RPA,多数人对它的认知还停留在“自动化工具”层面,能724小时不间断处理发票录入、凭证生成、银行对账等重复性财务工作,替代人工完成机械操作,实现“降本增效”。但事实上,随着大模型技术与财务场景的深度融合…...
2026职场进阶:数据分析技能的价值与应用
一、数据分析在职场中的核心价值市场需求增长:2026年企业对数据驱动决策的需求持续上升,数据分析成为跨行业通用技能。薪资竞争力:掌握数据分析能力的人才平均薪资高于同岗位非技术背景从业者。职业扩展性:从运营、市场到产品经理…...
VMware Unlocker终极指南:如何在Windows/Linux上免费解锁macOS虚拟机支持
VMware Unlocker终极指南:如何在Windows/Linux上免费解锁macOS虚拟机支持 【免费下载链接】unlocker VMware Workstation macOS 项目地址: https://gitcode.com/gh_mirrors/unloc/unlocker 你是否曾经想在Windows或Linux电脑上运行macOS虚拟机,却…...
