最大子数组和从暴力到Kadane算法:动态规划与分治全解析
这道经典的“最大子数组和”题算是力扣hot100里被翻牌次数最多的题目之一了。很多人在面试的时候都会被问到但它绝不是背个动态转移方程就能糊弄过去的题。如果用一句话概括核心给你一个整数数组让你找到一个连续的子数组让它的和最大返回这个最大值。看起来简单但里面藏着动态规划、贪心、分治好几层值得琢磨的东西。这篇文章我会把这道题从暴力到最优解完整拆开把每一步“为什么这么做”讲清楚顺便把刷题时容易踩的坑和面试时可能的追问都列出来。不管你是刚接触算法的小白还是准备冲刺大厂面试的老手这篇都能帮你把这道题吃透。1. 题目到底在问什么1.1 用大白话理解题意先翻译成人话。给你一个数组比如[-2, 1, -3, 4, -1, 2, 1, -5, 4]题目要你找一个连续的片段这个片段里的数字加起来的和是所有片段里最大的。注意“连续”这个词是重点。你不能跳着选打个比方这就好比在一列连续停靠的地铁站里选一段区间从A站坐到B站把每一站的客流量加起来找一个客流量总和最大的乘车区间。你不可能中间跳过某站也不能分段换乘只能是一路坐下去。再强调一下子数组要求元素在原数组中是连续相邻的。比如[4, -1, 2, 1]就是一个子数组它的和是6也是上面这个例子的答案。而[4, 2, 1]不是因为4和2在原数组中间隔着-1。1.2 暴力解法为什么不行很多人拿到题第一反应是我把所有子数组都枚举出来求个最大值不就行了吗思路没错但复杂度成问题。一个长度为n的数组子数组的数量是 $n*(n1)/2$ 个。如果对每个子数组再求和复杂度就是 $O(n^3)$。优化一点用前缀和可以把每个子数组求和优化到 $O(1)$这样总复杂度是 $O(n^2)$。但leetcode上数组长度动不动就是 $10^5$$O(n^2)$ 意味着要计算 $10^{10}$ 次必超时。所以要学会转变思路。暴力枚举之所以慢是因为它把“每个子数组”都当成独立个体重新计算。而更聪明的做法是找一个状态让后一个状态能从前一个状态转移过来这个状态就是“以某个位置结尾的最大子数组和”。1.3 这道题考察的能力最大子数组和是一道很典型的动态规划入门题但它考察的不只是动态规划。面试官可以从这道题延伸出很多考点状态定义是否清晰dp[i]表示什么很多人一开始会误以为dp[i]是整个数组的最大子数组和导致转移方程写不对。状态转移是否合理为什么取max(nums[i], dp[i-1] nums[i])这里面的逻辑能否讲清楚。空间优化如何从 O(n) 的dp数组降到 O(1)这体现你对状态依赖关系的敏感度。分治思想有些面试官会追问“如果不用贪心/DP你还能怎么做”此时分治解法就是加分项。边界处理数组全负数怎么办长度为1怎么办要不要允许空子数组这些细节决定了代码的健壮性。所以这道题看似简单其实是一座冰山水面下藏着很多面试官想捞的东西。2. 动态规划思路拆解从状态定义到状态转移2.1 状态定义dp[i]代表什么动态规划第一步是定义状态。我说一个很多人踩过的坑这道题最忌讳把dp[i]定义成“前i个元素中的最大子数组和”。为什么因为如果你这样定义当计算dp[i]时你需要知道“上一个最大子数组是否包含第i个元素”而这个信息你没存下来转移会很别扭。正确的状态定义是dp[i]表示以nums[i]作为结尾的连续子数组的最大和。注意“以 nums[i] 结尾”这几个字它是整道题的灵魂。把dp[i]理解为“数组的第 i 个位置必须被选中且这个子数组的终止位置必须在这里”。这样一来状态之间才有清晰的递推关系。举个例子数组[1, -2, 3]dp[0] 1以1结尾的最大和是1dp[1]以-2结尾的子数组有[-2]和[1, -2]最大和是-1dp[2]以3结尾的子数组有[3]、[-2, 3]、[1, -2, 3]最大和是3所以dp数组为[1, -1, 3]全局最大是3。2.2 状态转移方程的由来既然dp[i]是“以 i 结尾”的最大子数组和那么在上一个状态dp[i-1]的基础上考虑当我们要把nums[i]加入某个子数组时只有两种可能让nums[i]单独成为一个子数组也就是“从头开始”此时和为nums[i]。让nums[i]接在“以 i-1 结尾的最大子数组”后面此时和为dp[i-1] nums[i]。注意第2点为什么一定是dp[i-1]而不是别的前缀因为要以i结尾并且连续唯一能接的就是以i-1结尾的子数组。如果接的不是以i-1结尾的子数组中间就断开不连续了。所以转移方程就是dp[i] max(nums[i], dp[i-1] nums[i])等价写法是dp[i] nums[i] max(0, dp[i-1])后一种写法更好理解如果dp[i-1]是负数那我还不如不带它直接开一个新的子数组如果dp[i-1]是正数带上它能让和变大那就带。2.3 为什么答案不是dp[n-1]而是max(dp)这是很多新手最容易犯的错误。请你永远记住dp[i]只是“以 i 结尾”的最大和并不是整个数组的答案。真正的答案可能是以任意位置结尾的子数组中的最大值。比如数组[1, 2, -100, 3, 4]以最后一个位置4结尾的最大子数组是[3, 4]和是7刚好也是全局最大。但如果数组变成[5, -100, 1, 2]最后一个元素2结尾的最大和是3而全局最大其实是5。你不可能保证最大子数组一定结束在最后一个位置上。所以要么维护一个全局变量ans在计算每个dp[i]时更新它要么等dp数组算完后取max(dp)。2.4 空间压缩从O(n)到O(1)观察转移方程dp[i] max(nums[i], dp[i-1] nums[i])你会发现一个关键点计算当前状态只需要前一个状态不需要更早的状态。这是一个非常明显的“滚动更新”信号。于是我们完全没有必要开一个长度为 n 的dp数组只需要两个变量cur当前以 i 结尾的最大子数组和ans到目前为止的全局最大和循环里这样更新cur max(nums[i], cur nums[i]) ans max(ans, cur)这就是著名的Kadane算法也是这道题最优解的基本形态。它把空间复杂度从 O(n) 优化到了 O(1)。3. Kadane算法最优解的原理与代码实现3.1 Kadane算法的核心思想Kadane算法的名字听起来很高端其实本质就是“一边扫描一边更新当前连续和”。它采用的是贪心与动态规划结合的思想每到一个新位置我判断“之前积累的和”对我有没有帮助。如果帮助是正的我就继续累加如果帮助是负的还不如清零重来。这个“清零重来”的动作非常关键。生活化一点理解你手里攒了一堆钱但出现了负债。如果负债太多继续拿着只会越陷越深不如直接放弃旧账从今天重新开始攒。对应到算法中就是当cur nums[i]小于nums[i]时说明cur是负的负资产会拖累当前值所以选择从nums[i]作为新的起点。但要注意Kadane算法并不是真的切掉子数组它只是调整了“状态起点”。它的正确性建立在状态转移方程上cur永远代表以当前位置结尾的最大和这个值只会增加全局答案的可能不会丢解。3.2 代码实现C/Python/Java 示例给你几个主流语言的实现都是最优解直接抄作业没问题。先用Python写代码最简洁def maxSubArray(nums): cur ans nums[0] for num in nums[1:]: cur max(num, cur num) ans max(ans, cur) return ansC版本class Solution { public: int maxSubArray(vectorint nums) { int cur nums[0]; int ans nums[0]; for (int i 1; i nums.size(); i) { cur max(nums[i], cur nums[i]); ans max(ans, cur); } return ans; } };Java版本class Solution { public int maxSubArray(int[] nums) { int cur nums[0]; int ans nums[0]; for (int i 1; i nums.length; i) { cur Math.max(nums[i], cur nums[i]); ans Math.max(ans, cur); } return ans; } }注意这里初始化的细节cur和ans都初始化为nums[0]而不是0。这一步很重要原因下面单独讲。3.3 边界条件与初始化细节先看数组全为负数的情况比如[-3, -4, -5]。如果初始化为0那么循环里cur max(-4, 0 (-4)) -4看起来没问题。但初值ans 0会导致最终返回0而题目要求子数组至少包含一个元素所以正确答案应该是-3。当nums[0]是负数时把它作为初始ans就能避免“空子数组”混进来。再看长度为1的数组比如[7]。直接用nums[0]初始化后不会进入循环返回7正确。还有一点需要和面试官确认题目是否允许返回空子数组的和0力扣原题不允许但有一些变体或者商业场景里空数组会被认为和为0。如果在面试中遇到这题建议先问清楚“这个子数组必须至少包含一个元素对吧”这会显得你考虑问题周全。3.4 时间复杂度与空间复杂度分析Kadane算法只遍历了一遍数组所以时间复杂度是 O(n)。空间上只用了常量个变量空间复杂度 O(1)。这里很容易在回答时展开为什么O(n)是最优的因为只靠输入数组你至少要把每个元素看一眼才有可能得出正确答案所以下界就是O(n)。分治法虽然也能做但复杂度是O(n log n)空间O(log n)并不如Kadane。所以Kadane是这道题在“答案只要求返回最大和”前提下的最优解。4. 分治解法另一种思考方式4.1 分治的核心逻辑如果面试官追问“除了动态规划还有什么方法”分治解法是个很好的加分答案。分治的思想是把数组从中间切一刀分成左半和右半。那么整个数组的最大子数组和只可能出现在三个地方完全在左半部分完全在右半部分跨越中点一半在左一半在右前两种情况直接递归解决就行问题规模变成原来的二分之一。第三种情况需要单独处理从中间位置分别向左和向右扩展找到左半部分以中点结尾的最大连续和以及右半部分以中点开头中点右侧第一个元素的最大连续和两者加起来就是跨过中点的最大子数组和。4.2 合并区间时的四种情况很多人分治写不出来卡就卡在“跨中点情况”的合并上。这里我给你拆成四个小步骤从mid开始向左累加记录过程中出现的最大值leftSum。从mid 1开始向右累加记录过程中出现的最大值rightSum。跨中点的最大和就是leftSum rightSum。最终答案取max(左递归结果, 右递归结果, 跨中点结果)。注意向左扩展时为什么不能停下来因为可能暂时的累加和是负数但再加上更左边的正数后总和又会变大所以必须一直扩展到左边界并动态记录峰值。同理向右扩展也要一直进行。4.3 分治代码实现这里我给你一个用Python写清楚的分治版本def maxSubArray(nums): def divide_and_conquer(l, r): if l r: return nums[l] mid (l r) // 2 # 左半部分递归 left_ans divide_and_conquer(l, mid) # 右半部分递归 right_ans divide_and_conquer(mid 1, r) # 跨中点向左扩展 left_sum 0 left_max float(-inf) for i in range(mid, l - 1, -1): left_sum nums[i] left_max max(left_max, left_sum) # 跨中点向右扩展 right_sum 0 right_max float(-inf) for i in range(mid 1, r 1): right_sum nums[i] right_max max(right_max, right_sum) cross_ans left_max right_max return max(left_ans, right_ans, cross_ans) return divide_and_conquer(0, len(nums) - 1)这个递归的终止条件是l r也就是只有一个元素时直接返回该元素。跨中点合并的复杂度是O(n)每一层都要对当前区间进行一次线性扫描。4.4 分治与动态规划的对比分治法的时间复杂度是 O(n log n)空间复杂度是递归栈的 O(log n)。虽然不如Kadane但它的思想在很多高级数据结构里会用到比如线段树维护区间最大子段和。如果你把分治扩展一下就能解决“多次区间查询最大子数组和”的动态问题这也是后面可以继续深入的方向。动态规划的优势是代码短、速度快、好理解分治的优势是结构清晰便于扩展。两个解法建议都掌握面试的时候可以主动展示你从不同角度理解同一个问题。5. 常见错误与调试技巧实录5.1 初始化踩坑dp[0]忘记赋值导致问题有的同学会写一版“看起来没问题”的代码cur 0 ans 0 for num in nums: cur max(num, cur num) ans max(ans, cur)这个写法在数组有正有负时能跑出正确答案因为最终答案不会是0。但一旦数组全部是负数比如[-1, -2, -3]这个代码会返回0而正确答案是 -1。原因就是ans初始化为0相当于默认允许了一个空子数组出现。力扣原题里这个答案就是错的。避免方法是把初始值设为nums[0]并且循环从1开始。5.2 返回最大值还是返回dp最后一个元素这个坑我在教学时见过很多次。你如果写的是dp [0] * n dp[0] nums[0] for i in range(1, n): dp[i] max(nums[i], dp[i-1] nums[i]) return dp[-1]那么当最大子数组不在数组末尾时就会返回错误结果。比如[5, -100, 1, 2]dp为[5, -95, 1, 3]dp[-1]3但正确答案是5。必须维护一个ans变量或者最后返回max(dp)。很多人面试时在这翻车别小看这个细节。5.3 负数组的测试用例刷题的时候习惯性多测几个边界用例是很好的习惯。我觉得这道题至少测这三组全正数组[1, 2, 3]期望输出 6全负数组[-1, -2, -3]期望输出 -1混合数组[-2, 1, -3, 4, -1, 2, 1, -5, 4]期望输出 6尤其是全负数组最容易暴露初始化问题。很多看似正确的代码在普通用例能过到全负数组直接翻车。5.4 大数溢出的隐患如果数组元素是很大的整数比如10^9级别的数而且n也很大那么累加和可能超过int的表示范围。在C/Java里建议用long long或long来存cur和ans否则可能溢出得到错误结果。Python不用考虑这个因为整数可以无限大但在面试中如果你用C最好主动提一句“防止溢出用长整型”。6. 这类题型在面试中的延伸与应用6.1 变体一返回最大子数组的起止下标有时候光返回最大和还不够面试官会让你额外输出这个子数组在数组中的起始下标和结束下标。怎么改只需要在Kadane算法里多记录几个变量def maxSubArrayWithIndex(nums): cur ans nums[0] start end 0 tmp_start 0 for i in range(1, len(nums)): if cur nums[i] nums[i]: cur cur nums[i] else: cur nums[i] tmp_start i if cur ans: ans cur start tmp_start end i return ans, start, end这里的tmp_start是“当前子数组的临时起点”。当cur nums[i]小于nums[i]时说明我们决定从第i个元素重新开始所以临时起点更新为i。当cur刷新了ans时把临时起点和当前位置作为正式的起止下标。6.2 变体二环形数组最大子数组和如果数组是首尾相连的环形也就是你可以从末尾绕回开头找子数组那答案就有两种情况最大子数组没有跨越首尾边界它就是普通的最大子数组和。最大子数组跨越了首尾边界此时相当于从整个数组的和中减去一个“最小子数组和”。所以环形版本的解法是ans max(普通最大子数组和, total - 普通最小子数组和)但要注意如果数组全为负数普通最大子数组和就是最大的负数而total - 最小子数组和可能是0但空数组不允许所以这种情况要单独处理。这个变体在很多公司的面试题里出现过理解了这道题后环形版本其实就是在同一个思想上的小改造。6.3 变体三二维矩阵的最大子矩阵和还有一个进阶版本给定一个二维矩阵找一个子矩阵使得所有元素之和最大。这个问题的经典解法是一维最大子数组和的推广。具体做法是枚举矩阵的上边界和下边界把每一列的元素累加成一个一维数组然后对这个一维数组跑Kadane算法。这样一来二维问题就被压成了一维问题时间复杂度是O(n^3)。如果你把这道题吃透了“最大子矩阵”问题会轻松很多。6.4 贪心与动态规划的联系很多人分不清贪心和动态规划。在最大子数组和问题上Kadane算法其实同时具备贪心和动态规划两种视角。从状态转移角度看它是标准的动态规划从决策角度说每步只保留“以当前位置结尾的最大和”这是局部最优而局部最优又能推导出全局最优因此它也可以被理解为一种贪心策略。面试时如果能说出这句话“这题既可以用DP解释也可以用贪心解释Kadane算法是两者的结合”会给面试官留下很好的印象。说明你不只是在背代码而是理解了内在逻辑。最后再分享一个小技巧。刷这题时我建议你用手在纸上画两个例子一个是全负数一个是混合正负数。手动模拟一遍cur和ans的变化很多模糊的地方就会突然清晰起来。这道题代码虽然短但它几乎是所有“子数组类问题”的基石。把状态定义、转移方程、空间优化这三层吃透后面再遇到什么股票问题、最长递增子序列、最大子矩阵你都会有“原来都是同一个套路”的感觉。这道题我刷了很多遍每次给不同基础的人讲发现最后的瓶颈永远不是代码而是“为什么状态要定义成以i结尾”。别忘了这个核心比背十遍代码都有用。

相关新闻

MediaPlayer工程化实践:状态机、缓冲与音频焦点管理

MediaPlayer工程化实践:状态机、缓冲与音频焦点管理

简介:在Android多媒体开发中,MediaPlayer是处理音频与视频播放的核心组件,这份资源面向刚接触媒体播放功能的新手开发者,通过完整示例项目MediaPlayerDemo系统讲解其使用流程:创建MediaPlayer对象,通过setD…

2026/10/13 3:55:57 阅读更多 →
从零搭建RAG知识库:文档切分、向量化与检索优化实战

从零搭建RAG知识库:文档切分、向量化与检索优化实战

简介:这是一份面向前端初学者与进阶开发者的JavaScript知识库整理包,围绕JS语言核心与前端工程实践展开,帮助读者系统梳理从语法基础到项目规范的完整知识脉络。包内共26个文件,以19个Markdown笔记为主体,辅以3个Excel…

2026/10/13 3:55:57 阅读更多 →
从浏览器到网卡:TCP连接、三次握手与数据收发全流程解析

从浏览器到网卡:TCP连接、三次握手与数据收发全流程解析

读《网络是怎样连接的》读到 1.4.1 这一节时,我有种“前面的线终于收拢住了”的感觉:前面几节讲了 HTTP 请求消息长什么样、DNS 怎么把域名解析成 IP,但网页真正出现在屏幕上,还得靠操作系统内部的“数据收发操作整体流程”把它跑…

2026/10/13 3:55:57 阅读更多 →

最新新闻

吉林大学编译原理实战:Lex/Yacc/C手写编译器全流程

吉林大学编译原理实战:Lex/Yacc/C手写编译器全流程

简介:本资源是吉林大学编译原理课程的完整实践配套包,面向计算机专业本科生、考研备考学生及编译器技术初学者,聚焦词法分析、语法解析、中间代码生成与目标代码实现等核心能力训练。压缩包共27个文件,涵盖4个Java源码&#xff08…

2026/10/13 4:39:10 阅读更多 →
Open Code Review:可验证、可教学、可持续的开源协作新范式

Open Code Review:可验证、可教学、可持续的开源协作新范式

1. 这不是代码审查,是开源协作的“显微镜”与“压力测试仪”“open-code-review”这个词组乍看像一个技术名词,实则是一套正在悄然重塑开发者协作范式的实践方法论。它不依赖某个特定工具、不绑定某家平台、也不属于某类官方流程——它本质上是一种可被任…

2026/10/13 4:39:10 阅读更多 →
Windows下MySQL安装与配置全攻略:从ZIP包到服务注册的实战指南

Windows下MySQL安装与配置全攻略:从ZIP包到服务注册的实战指南

1. 安装前想清楚:版本选择与下载1.1 为什么不要直接点"最新版"很多人第一次装 MySQL,习惯性直接去官网下最新版本,结果装完连配置都找不到,或者跟老项目的连接驱动不兼容。我在 Windows 上装过不少次 MySQL,…

2026/10/13 4:39:10 阅读更多 →
CWRU轴承数据集深度解析:从原始.mat到故障诊断Pipeline

CWRU轴承数据集深度解析:从原始.mat到故障诊断Pipeline

简介:本资源是面向机械故障诊断研究者、研究生及工业智能运维工程师的经典轴承数据集实践套件,聚焦滚动轴承多工况故障识别与模型验证需求。资源完整包含CWRU原始振动信号(165个MAT文件,涵盖正常、内圈/外圈/滚珠不同故障尺寸共10…

2026/10/13 4:39:10 阅读更多 →
LiteLLM:大模型协议统一与智能路由的工程实践

LiteLLM:大模型协议统一与智能路由的工程实践

1. 从“调用大模型像调用API”说起:LiteLLM到底在解决什么真问题?你有没有过这样的经历:上周刚用OpenAI的gpt-4-turbo跑通一个客服对话系统,这周客户突然要求切换成Anthropic的claude-3-haiku——结果发现,光是把opena…

2026/10/13 4:39:10 阅读更多 →
开放代码审查:让评审过程透明可追溯的团队实践

开放代码审查:让评审过程透明可追溯的团队实践

代码审查这件事,几乎所有团队都说自己在做,但真正做好的没几个。我见过太多项目把Review变成了例行公事:上线前临时拉人点个“同意”,评论区里互相打哑谜,新人面对一堆历史PR完全不知道当初为什么这么写。今天想聊的“…

2026/10/13 4:38:09 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目,我最大的感受是,大部分坑不是出在技术前沿,而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节,最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了,很难不碰到舵机控制这道坎。做智能小车要转方向,做机械臂要抬关节,做云台要偏航俯仰,背后都是同一个东西在干活:舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”?——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台?或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜?又或者,在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 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/12 21:05:09 阅读更多 →
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/12 14:48:49 阅读更多 →
黑夜航拍船只数据集训练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/12 18:11:17 阅读更多 →