doocs/leetcode 题解:LCP 77. 符文储备——排序 + 滑动窗口求相邻魔力值差不超过 1 的最长可携带符文序列
示例工程【免费下载链接】leetcodeLeetCode solutions in any programming language | 多种编程语言实现 LeetCode、《剑指 Offer第 2 版》、《程序员面试金典第 6 版》题解项目地址https://gitcode.com/doocs/leetcode点击查看免费下载导读本文围绕 LeetCode LCP 系列题「LCP 77. 符文储备」展开完整讲解题目的约束条件、两个官方示例并深入剖析其核心解法——先将符文魔力值排序再用双指针维护滑动窗口找出「相邻魔力值相差不超过 1」的最长连续段。读完本文你将掌握该类「差值约束 最大化子集」问题的通用建模思路并能对照 doocs/leetcode 仓库中 Python、Java、C、Go、TypeScript 五种语言的 官方题解与源码 独立编写和验证代码。一、题目描述远征队在出发前需要携带一些「符文」作为后续的冒险储备。runes[i]表示第i枚符文的魔力值。他们将从中选取若干符文进行携带并对这些符文进行重新排列以确保任意相邻的两块符文之间的魔力值相差不超过1。请返回他们能够携带的符文最大数量。输入runes [1,3,5,4,1,7] 输出3本题来自 LeetCode LCP力扣杯 / 程序员面试系列在仓库中的编号为「LCP 77. 符文储备」难度为简单是一道典型的「排序 滑动窗口 / 双指针」应用题。二、示例与数据范围示例 1输入runes [1,3,5,4,1,7]输出3解释最佳的选择方案为[3,5,4]将其排列为[3,4,5]后任意相邻的两块符文魔力值均不超过1携带数量为3。其他满足条件的方案为[1,1]和[7]数量均小于3因此返回可携带的最大数量3。示例 2输入runes [1,1,3,3,2,4]输出6解释排列为[1,1,2,3,3,4]可携带所有的符文。提示1 runes.length 10^40 runes[i] 10^4从数据范围可以判断n最大为10^4魔力值是非负整数且值域上限同样为10^4。这决定了我们既可以选择O(n log n)的排序类算法也保留了值域受限时「桶计数」优化的想象空间见后文第七节。三、核心思路把「可重新排列」转化为排序后的连续段题目的难点在于约束条件是「重新排列后任意相邻两块差值不超过 1」这似乎与排列顺序有关。但仔细观察可以发现一个关键事实对于任意一组选取的符文把它们按魔力值从小到大排序恰好是让相邻差值最小的排列方式。因此一个选取方案合法当且仅当它排序后任意相邻两项的差都不超过 1。原文档的「思考」部分也给出了同样的分析n 10^4要求选出一个子集任意两块魔力差的绝对值不超过1并最大化子集大小差值条件与顺序无关排序后合法元素必落在一段连续区间排序后用左端i维护当前段相邻差大于1则重开窗口否则用j - i 1更新答案。进一步推导假设排序后的数组中存在三个元素a b c如果c - a 1那么必然有b - a 1且c - b 1即中间的元素一定也能被纳入同一个合法集合。这意味着任何一个合法的携带方案都对应于排序后数组中的一段连续区间反过来排序后任意一段「相邻差均不超过 1」的连续区间其全部元素构成的集合都是合法方案。于是问题被干净地转化为在排序后的runes数组中寻找「相邻元素之差均不超过 1」的最长连续子数组的长度。四、方法一排序 滑动窗口双指针4.1 算法流程将runes按魔力值从小到大排序初始化窗口左端i 0答案ans 0用右端j从左到右遍历排序后的数组若j 0且runes[j] - runes[j-1] 1说明当前元素与前一个元素「断档」合法段被切断令i j重开窗口否则窗口[i, j]内的相邻差均不超过 1用窗口长度j - i 1更新ans遍历结束后ans即为可携带的最大符文数量。正确性说明由于合法集合在排序后必然是连续段而相邻差超过 1 的「断点」一定是两个合法段的天然分界因此每次断档时重开窗口就能枚举出所有可能的合法段取其中长度最大者即为答案。4.2 复杂度分析按原文档给出的结论时间复杂度O(n × log n)主要来自排序空间复杂度O(log n)来自排序过程如快速排序的递归栈开销。其中n是数组runes的长度。排序之后的双指针扫描是单趟O(n)不是性能瓶颈。五、多语言实现与逐行解读该题在仓库目录 lcp/LCP 77. 符文储备 下提供了五种语言的独立实现文件Solution.py、Solution.java、Solution.cpp、Solution.go、Solution.ts与 README 中的题解代码一一对应。下面逐一解读。5.1 Python3参考源码Solution.pyclass Solution: def runeReserve(self, runes: List[int]) - int: runes.sort() ans i 0 for j, x in enumerate(runes): if j and runes[j] - runes[j - 1] 1: i j else: ans max(ans, j - i 1) return ans要点说明runes.sort()原地升序排序i为窗口左端ans为答案enumerate同时给出下标j与元素值xx即runes[j]用于与runes[j-1]比较if j and ...利用了 Python 中0为假值的特性当j 0第一个元素时条件短路为假进入else分支将ans置为1——这保证了对单元素窗口的处理当相邻差大于 1 时i j重开窗口否则用j - i 1更新最大长度。5.2 Java参考源码Solution.javaclass Solution { public int runeReserve(int[] runes) { Arrays.sort(runes); int ans 0; for (int i 0, j 0; j runes.length; j) { if (j 0 runes[j] - runes[j - 1] 1) { i j; } else { ans Math.max(ans, j - i 1); } } return ans; } }要点说明Arrays.sort(runes)对int[]原地排序双下标i窗口左端与j扫描指针在同一循环内声明j即窗口右端与 Python 版本逻辑完全一致j 0时若runes[j] - runes[j-1] 1则i j重开窗口否则Math.max更新答案。5.3 C参考源码Solution.cppclass Solution { public: int runeReserve(vectorint runes) { sort(runes.begin(), runes.end()); int ans 0; for (int i 0, j 0; j runes.size(); j) { if (j runes[j] - runes[j - 1] 1) { i j; } else { ans max(ans, j - i 1); } } return ans; } };要点说明sort(runes.begin(), runes.end())对vectorint升序排序if (j ...)与 Python 写法同源j 0时短路跳过断档判断进入else分支初始化答案注意j是size_t类型时j - 1需保证j 0才参与运算该写法通过短路求值规避了无符号下溢问题。5.4 Go参考源码Solution.gofunc runeReserve(runes []int) (ans int) { sort.Ints(runes) i : 0 for j, x : range runes { if j 0 x-runes[j-1] 1 { i j } else if t : j - i 1; ans t { ans t } } return }要点说明sort.Ints(runes)原地排序函数使用具名返回值(ans int)因此末尾直接return即可返回ansrange runes同时给出下标j与元素值x断档判断直接比较x与runes[j-1]更新答案时使用 Go 特色的else if短语句在条件内声明局部变量t : j - i 1当ans t时赋值写法紧凑且作用域清晰。5.5 TypeScript参考源码Solution.tsfunction runeReserve(runes: number[]): number { runes.sort((a, b) a - b); let ans 0; let i 0; for (let j 0; j runes.length; j) { if (j 0 runes[j] - runes[j - 1] 1) { i j; } else { ans Math.max(ans, j - i 1); } } return ans; }要点说明runes.sort((a, b) a - b)必须显式传入比较器JS/TS 默认的Array.prototype.sort按字符串字典序排序直接调用sort()会把10排在2前面导致数值排序错误这是本题最容易踩的坑其余逻辑双指针、断档重开窗口、Math.max更新与其他语言一致。六、边界情况与易错点结合题目约束与源码实现以下几个边界值得特别注意场景行为说明runes只有一个元素返回1首轮j 0走else分支ans被置为1与「任意相邻」约束空集无关单独一块符文必可携带所有魔力值相同如[5,5,5]返回n相邻差为0 1全程不断档窗口覆盖整个数组存在重复值如[1,1,2,2]差值0合法重复值之间的差为 0不触发断档可全部纳入同一窗口魔力值为0合法0 runes[i] 10^40与1的差为1可正常参与窗口计算相邻差恰好为1不断档断档条件严格为 1差等于1时窗口继续扩展相邻差大于1时重开窗口断点处i j当前元素单独成段其长度由后续轮次的else分支计入最易出错的点TypeScript/JavaScript 中忘记传(a, b) a - b比较器导致数值排序变成字典序排序以及判断断档时误用「窗口内最大值与最小值之差」而非「相邻元素之差」——本题约束的是相邻两块差值不超过 1而非整个窗口跨度两者含义完全不同。七、思路延伸值域受限下的桶计数等价实现题目提示中0 runes[i] 10^4即魔力值是非负整数且值域有限。从第三节的结论可以推导出一个等价的视角由于魔力值是整数且排序后相邻差不超过 1合法集合的不同魔力值必然构成一段连续的整数区间区间内每个值可出现任意多次。由此可以得到一种不排序的替代实现思路先统计每个魔力值v的出现频次cnt[v]然后扫描值域找出「频次大于 0 的连续整数区间」中最长的一段区间携带数量即为该区间内所有频次之和。其复杂度为O(n M)M为值域上限10^4在n接近10^4时与排序方案相当但当n远大于值域时例如大量重复数据桶计数可以省去排序的O(n log n)开销。需要说明的是该变体是基于题目约束自行推导的等价思路仓库官方题解采用的是前述「排序 滑动窗口」方案两种方法结论一致可以互为验证。八、仓库资源速览本主题在仓库中的完整资源如下便于对照学习与验证题解文档题目描述 解法 全语言代码Solution.pyPython3 实现Solution.javaJava 实现Solution.cppC 实现Solution.goGo 实现Solution.tsTypeScript 实现LCP 系列题解索引可按题号快速定位全部 LCP 题解总结「LCP 77. 符文储备」表面上是带排列约束的选取问题核心洞察在于两点一是排序是让相邻差最小的最优排列使「任意相邻差 ≤ 1」与顺序解耦二是合法集合必然对应排序数组中的连续段从而把问题归约为「找相邻差均 ≤ 1 的最长连续子数组」。基于此排序 双指针滑动窗口即可在O(n log n)时间内求解五种语言的实现结构完全一致唯一需要注意的差异点是 JS/TS 的排序比较器。该题的「先排序消解顺序约束、再双指针扫连续段」套路同样适用于其他「差值 / 间隔约束 最大化子集」类问题值得熟练掌握。赞分享示例工程【免费下载链接】leetcodeLeetCode solutions in any programming language | 多种编程语言实现 LeetCode、《剑指 Offer第 2 版》、《程序员面试金典第 6 版》题解项目地址https://gitcode.com/doocs/leetcode点击查看免费下载相关推荐LCP 77「符文储备」多语言题解精讲排序 双指针滑动窗口求最大携带符文数LCP 77「符文储备」多语言题解精讲排序 双指针滑动窗口求最大携带符文数 本篇基于 doocs/leetcode 开源仓库中 lcp/LCP 77. 符示例工程Odoo AI 助手配置指南5 分钟搭好你的 7×24 智能客服Odoo AI 助手配置指南5 分钟搭好你的 7×24 智能客服 客户半夜问价没人回同一个问题被问了一百遍用 Odoo 就能搭出一个会自己回复的 Odoo企业应用后端电商codeforces-go 力扣杯 2023 春·战队赛题解runeReserve 排序后相邻扫描求最长符文段codeforces go 力扣杯 2023 春·战队赛题解runeReserve 排序后相邻扫描求最长符文段 本篇题解对应 leetcode/season/科学计算上一篇ezdxf 解析 DXF 代理图形Proxy Graphic二进制块ACGi 指令流与 Opcode 全解读下一篇使用 DataHub matillion-dpc Connector 摄取 Matillion Data Productivity Cloud 元数据与血缘创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

风光制氢合成氨系统优化建模与Python实现详解

风光制氢合成氨系统优化建模与Python实现详解

做能源系统优化的人,这两年应该没少听到“风光制氢”这个方向——风电场、光伏电站出力不稳定,直接并网会给电网带来冲击,于是大家把目光转向“先用绿电制氢、再把氢合成氨”的路线。氨这东西好处太多了:能量密度比氢高&#xff0…

2026/10/17 9:58:32 阅读更多 →
三星Tab E T560/T561线刷救砖指南:固件分区、Odin步骤与避坑

三星Tab E T560/T561线刷救砖指南:固件分区、Odin步骤与避坑

简介:三星SM-T560/T561平板适用的第三方LineageOS 14.1刷机包,基于安卓7.1.2,用于替换原厂安卓4.4.4系统,原系统老化严重,应用无法安装、浏览器连百度都打不开,对于还想让9.6寸老平板继续发挥余热的用户&am…

2026/10/17 9:58:05 阅读更多 →
Notepad++排版实战:缩进、正则与插件的完整指南

Notepad++排版实战:缩进、正则与插件的完整指南

1. 先搞明白:Notepad 排版到底在解决什么问题1.1 排版不等于美化提到 Notepad 排版,很多人第一反应是“不就是调一下自动换行、改改字号嘛”。这种理解不能说错,但太浅了。我最早也是这么想的,直到有次处理一份十几万行的配置文件…

2026/10/17 9:56:04 阅读更多 →

最新新闻

RAG实战拆解:让大模型学会查资料,解决知识冻结

RAG实战拆解:让大模型学会查资料,解决知识冻结

最近被频繁问到的一个场景:某个系统三个月前升级了新版本,新功能、新参数、新的注意事项都写在内部文档里了,但你去问大模型,它给你答的仍是旧版本的老一套。更尴尬的是,业务方拿着文档找过来:“这上面写得…

2026/10/17 14:06:57 阅读更多 →
通信工程毕设选题全攻略:避开三大误区,选对能答辩的高分题目

通信工程毕设选题全攻略:避开三大误区,选对能答辩的高分题目

每到毕业季,通信工程专业的学弟学妹找我聊的最多的就是毕设选题。问来问去,无非是这几句话:"老师给了一堆题目,看不出区别""想做个新一点的,又怕做不出来""网上搜到的都是前几年的老题&#…

2026/10/17 14:06:57 阅读更多 →
低空经济产业链全解读:从原材料到运营的入局机会与避坑指南

低空经济产业链全解读:从原材料到运营的入局机会与避坑指南

简介:面向低空经济产业链研究者、投资人与政策制定者的专业解析文档,系统拆解“原材料—核心制造—应用场景”全链条,而非泛泛介绍。上游梳理钢材、铝合金、工程塑料、陶瓷基材、碳纤维等关键材料的研发创新与供应优化;中游聚焦无…

2026/10/17 14:06:57 阅读更多 →
免训练动态聚焦DyFo:让多模态大模型看清细节的工程实践

免训练动态聚焦DyFo:让多模态大模型看清细节的工程实践

前阵子读了一篇CVPR的论文,标题里有个词特别吸引我——"免训练动态聚焦"。DyFo这个名字乍一听有点学术,但它解决的问题非常接地气:现在的多模态大模型已经能看懂整张图,可一旦你想让它盯住图里某个很小的细节——比如票…

2026/10/17 14:06:57 阅读更多 →
从IDE到IAE:意图增强环境如何重构开发工作流

从IDE到IAE:意图增强环境如何重构开发工作流

1. 从"编辑器思维"到"意图思维"的转变 第一次看到"IDE 已死,IAE 当立"这个说法,我第一反应是:又一个标题党。毕竟 VS Code 装机量摆在那里,JetBrains 全家桶也活得好好的,说 IDE 死了&a…

2026/10/17 14:06:57 阅读更多 →
数据结构链表实战:一元稀疏多项式计算与C语言实现

数据结构链表实战:一元稀疏多项式计算与C语言实现

这几年我带过不少学生做数据结构上机题,要说哪道题最容易被低估,一元稀疏多项式的计算绝对排得上号。这道题来自某高校的数据结构课程上机环节,题面看起来只是“计算两个多项式之和/积”,但实际做起来牵扯到链表的设计、有序插入、…

2026/10/17 14:05:57 阅读更多 →

日新闻

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

简介:《DeepSeek使用方法.pdf》是一份面向DeepSeek入门及进阶用户的完整使用指南,重点围绕V3与R1两款模型的能力差异与适用场景展开,帮助读者根据任务类型与成本选择合适的模型。资源共1个PDF文件,压缩包大小约311KB,篇…

2026/10/17 0:00:25 阅读更多 →
200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

简介:这是一份聚焦DeepSeek提示词优化的《200Deepseek润色指令》PDF文档,共收录两百余条可直接套用的润色指令,涵盖语法修正、风格统一、逻辑梳理、表达精炼等维度,并针对商务写作、学术论文、广告文案等场景给出差异化建议。文档…

2026/10/17 0:00:25 阅读更多 →
OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

简介:本资源是一份基于OpenCV的本科课程设计完整报告,面向计算机视觉初学者、图像处理学习者及高校通信/信息类专业学生,解决物体智能计数与检测结果结构化记录的实际问题。项目覆盖图像预处理、轮廓检测、边界框绘制、轨迹栏交互式参数调节、…

2026/10/17 0:00:25 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/16 21:35:51 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/17 1:44:59 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/16 15:04:24 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 21:54:38 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 3:49:43 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →