链表每 k 个一组翻转:核心思路与递归迭代实现
1. 题目到底在问什么先别急着写代码链表中的节点每 k 个一组翻转这是一个非常典型的单向链表操作题。这句话拆开看有三层要求按 k 个节点划分成一组、每个分组内部做逆序、组与组之间保持原有相对顺序。很多第一次接触这道题的朋友都会写一个“局部反转函数”然后发现拼接时总差那么一口气。它不像反转整个链表那样只需要一个头节点因为每次翻转完之前的链表尾巴要能正确接到新的组头同时这一组的旧头还要作为下一组的前驱。所以我建议拿到题目先别急着写循环先把“分组翻转”的物理过程在纸上画明白。这道题特别适合练两件事一是对链表指针的掌控力二是递归和迭代两种思维的切换。对刚入门链表操作的开发者来说完整手写一遍能帮你解决很多“看起来会但一写就乱”的问题对于准备面试的人来说它又是一个很容易被追问边界条件的高频题。不管你现在处于哪个阶段只要吃透这一题很多链表面试题都会豁然开朗。1.1 从一段链表说起举个例子。输入链表是 1 - 2 - 3 - 4 - 5k 2期望的结果是 2 - 1 - 4 - 3 - 5。直观理解就是你有一排人从头开始每 2 个人分成一小队每小队内部前后调换但小队之间的顺序不变。如果是 k 3则结果是 3 - 2 - 1 - 4 - 5因为最后一组只剩 4 和 5 两个节点不足 3 个所以保持原样。这个“不足 k 个不翻转”的规则就是全题最容易被忽略的地方。很多人翻转时没先数数结果把末尾不足 k 个的节点也倒过来输出就错了。为什么这里用“每 k 个一组”而不是直接“按固定大小切成多段”因为链表长度未知需要先遍历得到长度而一次遍历中你没法预知后面还有几个节点所以只能“走一步看一步”先尝试走 k 步如果走满了 k 步说明这一组完整可以翻转如果走不到 k 步说明剩余不足一组直接保留原顺序结束。这个“先试探再操作”的思路几乎可以套用到所有分段链表问题上。很多初学者会想着先翻转、后判断这是行不通的因为一旦翻转动作开始原来的节点顺序就被破坏了想再恢复原样会很麻烦。1.2 你需要关注的三个边界在正式动手前先把边界列出来。这里用一个表格总结常见情况输入情况处理方式head 为空直接返回空指针k 1不进行任何翻转原链表返回链表长度恰好等于 k整条链表翻转一次链表长度大于 k 且是 k 的整数倍每一组都翻转最终整条链表全部翻转链表长度大于 k 但不是 k 的整数倍前若干组翻转末尾剩余不足 k 个的节点保持原序为什么强调 k 1因为当 k 1 时每组只有一个节点翻转等于没翻转。如果不加保护进入翻转循环后可能出现prev-next指针错误或者死循环。空链表也是一样如果 head 本身是 nullptr任何对 head-next 的访问都会触发空指针异常所以代码开头先做一次空判断是必须的。链表长度恰好等于 k 这种情况也很容易想当然因为此时最后一组就是整条链表翻转完后新头应该返回原来的第 k 个节点如果用了虚拟头节点只需要返回 dummy.next 即可。这些边界虽然看起来简单但每条都能筛选掉一批“写得出来但不严谨”的代码。与其等到测试时才发现不如在最开始就把它们纳入设计。2. 核心思路分组翻转的本质是“拆装”链表反转本身并不难难的是“分组”和“拼接”。如果把整个题目拆成动作来看可以概括为三步找到一组 k 个节点翻转这一组内部再把这一组接回原来的链表中。这个“拆下来、翻过来、装回去”的过程和日常修水管很像你得先关掉这一段的连接把管子反向后再重新对接两头。下面我详细拆解每一步的原理。2.1 翻转子链表的基本动作先回顾最基础的链表反转。假设要反转从 head 开始到链表末尾的整段节点三指针迭代的标准写法是ListNode* reverseList(ListNode* head) { ListNode* prev nullptr; ListNode* cur head; while (cur) { ListNode* next cur-next; cur-next prev; prev cur; cur next; } return prev; }这个函数会把输入链表完整反转新链表的头是原来的尾巴。但本题不能直接把这个函数拿过来用因为我们需要翻转的是一个被截断的区间而不是从某个节点一直到末尾。真正的需求是给定一个起始节点 groupStart给定一个结束节点 tailtail 指向当前分组的下一组第一个节点我们要翻转从 groupStart 开始到 tail 之前的这一段节点并且翻转完成后这一段的新头能接回前驱旧头能接上 tail。这里引入一个非常实用的概念半开区间。我们把要翻转的子链表定义成[groupStart, tail)意思是包含 groupStart但不包含 tail。tail 是当前分组的下一个节点它同时充当翻转操作的“终止标记”。在这个半开区间内做翻转只要让循环条件写成cur ! tail就可以精准控制翻转范围。这样做的好处是代码里不需要额外记录 groupStart 之前的节点也不需要再单独找 groupStart 之后的节点tail 天然就是边界。后面你会看到这个约定能让代码简洁非常多。在翻转循环里我们会用 prevNode 记录上一个被处理过的节点。标准反转中初始 prev 是 nullptr但在本题的半开区间翻转中初始 prev 应该设置为 tail。为什么因为翻转结束后原来的 groupStart 会成为这一组的尾巴它的 next 必须指向 tail这样这一组才能和后面部分接上。如果初始 prev 设置为 nullptr翻转完成后的尾巴会指向 null你还得额外把原来的 groupStart 的 next 改成 tail多一次手动操作。直接把 prev 初始化为 tail这个问题就自动解决了。这一点很多讲解不会细说但实际写代码时非常重要。2.2 为什么长度计数必须在翻转之前完成我在 1.1 里提到过“先试探再操作”这里展开讲讲原因。链表是单向的你只能从前往后走不能回头。如果一开始不数满 k 个节点就直接开始翻转一旦发现后面不够 k 个了你已经修改了前面几个节点的 next 指针想把它们恢复原样就会变得很麻烦。越早发现不足损失越小最坏情况是翻转了一部分才发现长度不够那时整个链表的结构已经乱了除非你把每个被修改的旧指针都保存下来才能还原但这会让代码复杂许多。所以每轮循环的第一步永远是从当前组头开始用一个临时指针走 k 步确认这一组是完整的。这一步的时间复杂度是 O(k)每一轮都做一次但整体复杂度依然是 O(n)。原因很简单每个节点至多被“数”一次又被“翻转”一次总访问次数大约是 2n 到 3n 的量级常数不影响复杂度评估。有些人会先遍历一次链表求总长度然后用长度除以 k 得到完整组数再做那么多轮翻转。这种做法其实是把“每一轮数 k 个节点”提前合并成了一次整体数长度的操作总体复杂度同样是 O(n)区别只在于代码结构不同。两种方案都正确但在不额外允许遍历链表的前提下边数边翻转更符合题目原意。这里还有一个容易混淆的点翻转之后原来的组头会变成组尾巴原来的组尾会变成组头。因此下一轮循环不能再用上一轮记录的位置来定位起点必须让 prev 指针指向当前组的旧头因为旧头就是下一组的前驱而下一组的起点可以通过prev-next拿到。只要理解了“翻转后位置互换”这一点就不会写错 prev 的更新逻辑。2.3 递归写法与迭代写法的取舍递归版本的核心思想非常简洁先翻转当前 k 个节点然后把翻转后的组尾巴接到“后面链表递归处理后的新头”上。假设当前组头是 head先利用一个 cur 指针向后走 k 步走到第 k1 个节点 nextHead。如果走不到 k 步说明剩余不足一组直接返回 head。如果走得到说明当前 k 个节点足够翻转于是对这 k 个节点做一次区间翻转翻转结束后原来的第 k 个节点变成了新的组头 prev原来的 head 变成了组尾巴。最后执行head-next reverseKGroup(nextHead, k)就能把当前组拼接在后面链表处理的结果上并返回 prev。递归的优点是很直观代码量也少特别适合在面试中先展示思路。但它的缺点也很明显递归深度近似等于链表长度除以 k。当链表很长、k 很小时递归深度可能会达到上万个层级导致栈溢出。工程上更倾向用迭代版本通过虚拟头节点和 prev 指针把所有空间复杂度控制在 O(1)。面试时你可以先讲递归再分析它的问题最后给出迭代版本这样会让面试官看到你具备“从正确到最优”的完整思考过程。实际项目里写链表处理代码我几乎都会选择迭代因为它不依赖调用栈出问题也更容易定位。3. 实操完整代码与关键细节现在给出两种主流实现的完整代码并逐行讲解关键步骤。代码以 C 为例但逻辑可以平移到其他语言。3.1 先定义节点结构在练习链表问题时要自己先定义一个可用节点结构。C 里通常长这样struct ListNode { int val; ListNode *next; ListNode() : val(0), next(nullptr) {} ListNode(int x) : val(x), next(nullptr) {} ListNode(int x, ListNode *next) : val(x), next(next) {} };如果是在刷题环境里这个结构一般已经提供好了不需要手动定义。但自己练习时建议手动写一遍这样能对所有字段熟悉起来。注意创建节点时要显式初始化 next否则节点里的 next 可能保存了一个随机地址后续遍历时大概率崩溃。写链表的日常工程代码最怕的就是野指针和未初始化成员。还有一点这里的节点可能是已经存在的链表节点我们只是修改它们之间的引用关系并不需要创建新节点。除非题目要求返回一个新链表否则不要随意 new 额外节点避免内存管理和所有权混乱。3.2 迭代实现带头节点处理迭代版本我使用一个虚拟头节点 dummy它可以有效避免链表头被更换后需要单独处理前置节点的麻烦。完整代码如下class Solution { public: ListNode* reverseKGroup(ListNode* head, int k) { if (head nullptr || k 1) return head; ListNode dummy(0); dummy.next head; ListNode* prev dummy; while (true) { ListNode* groupStart prev-next; ListNode* tail groupStart; int count 0; while (tail ! nullptr count k) { tail tail-next; count; } if (count k) break; ListNode* cur groupStart; ListNode* prevNode tail; while (cur ! tail) { ListNode* nxt cur-next; cur-next prevNode; prevNode cur; cur nxt; } prev-next prevNode; prev groupStart; } return dummy.next; } };这段代码有几个关键点值得停下来认真分析。第一dummy.next head这一行让 dummy 成为头节点的前置节点。后续每翻转一组prev-next会被更新成新的组头。即使第一次翻转完成后真正的链表头变了返回时只需要取dummy.next不需要再写一套“如果头变了就返回新头”的判断逻辑。虚拟头节点在这里的收益很大。第二tail指针用来做两件事一是判断剩余长度是否足够 k二是作为半开区间翻转的右边界。每一轮开始时groupStart取prev-next它一定是当前尚未处理的第一个节点。然后 tail 从 groupStart 出发连续往后走 k 步。如果中途遇到 nullptr说明剩余节点不足 k 个循环结束。如果走满 k 步即使 tail 恰好为 nullptr也没问题因为这说明这一组正好取完了链表剩余的所有节点翻转区间是[groupStart, nullptr)本质上是翻转一整段余下链表。第三翻转循环里的prevNode tail是关键。tail 是下一组的第一个节点它作为翻转过程中的“虚拟前驱”。翻转过程中每访问一个节点都让它的 next 指向上一个节点同时把 prevNode 前移。循环结束后prevNode 停在当前组的新头位置groupStart 则自然变成了当前组的尾巴。由于我们一开始没有把 prevNode 设为 nullptr所以翻转完成后不用额外设置groupStart-next tail它已经通过第一次的cur-next prevNode被正确连接到了 tail。第四翻转结束后执行prev-next prevNode把上一组的尾巴连接到本组的新头。然后prev groupStart因为原 groupStart 现在是本组的尾巴它就是下一组翻转时的前置节点。这一步非常容易写错很多人会把 prev 更新为 prevNode结果下一轮循环里 groupStart 就变成了已经处理完的中间节点导致死循环。记住prev 永远指向“当前已处理链表段的最后一个节点”也就是本组翻转后的尾巴 groupStart。3.3 递归实现更简洁但别踩栈溢出递归版本代码如下ListNode* reverseKGroupRecursive(ListNode* head, int k) { ListNode* cur head; int count 0; while (cur ! nullptr count k) { cur cur-next; count; } if (count k) return head; ListNode* prev cur; ListNode* node head; while (node ! cur) { ListNode* nxt node-next; node-next prev; prev node; node nxt; } head-next reverseKGroupRecursive(cur, k); return prev; }递归版本的逻辑很顺先向右探 k 步如果不足 k 个就返回 head。如果够 k 个cur 此时指向第 k1 个节点。接着用 prev 初始化为 cur对 head 到 cur 之前的节点做翻转。这个翻转和迭代里的内部翻转完全一样区别只是翻转完成后head 现在变成了本组尾巴所以它的 next 需要指向递归调用返回的后半段新头。最终返回 prev它才是这 k 个节点翻转后的新头。递归版本的优点是代码少、思路清晰很适合在刚拿到题目时快速表达自己的想法。但它也有明显问题每层递归都要消耗栈空间深度约为 n / k。如果链表有十万个节点k 又小递归调用就会很深很可能爆栈。所以我自己实际手写生产级代码时从不使用递归处理长链表面试写完递归版本后也一定会补一个迭代版本表示自己理解两种方案的取舍。4. 测试与调试我踩过的那些坑链表问题最大的特点就是代码看起来似乎对了一跑就出各种玄学问题。下面这些问题都是我实际调试时遇到过的整理出来供大家避坑。4.1 链表长度刚好是 k 的倍数 vs 不是倍数先准备一组测试用例。如果链表是 1 - 2 - 3 - 4k 2期望输出是 2 - 1 - 4 - 3。因为链表长度 4 刚好是 2 的整数倍所以每一组都翻转所有节点都会被重新排序。如果链表是 1 - 2 - 3 - 4 - 5k 2期望输出是 2 - 1 - 4 - 3 - 5末尾的 5 不动。如果用 k 3 测 1 - 2 - 3 - 4 - 5期望输出是 3 - 2 - 1 - 4 - 5。这些用例能覆盖“是整倍数”和“不是整倍数”两种情况。调试的时候建议自己写一个简单的printList函数void printList(ListNode* head) { while (head ! nullptr) { cout head-val - ; head head-next; } cout nullptr endl; }在每次翻转结束后调用它看链表是否符合预期。不要只在最终结果处打印因为出错的位置可能隐藏得很深。我调试时经常在“翻转前”“翻转后”“拼接后”各打印一次这样能快速定位是哪一步把链表搞乱的。链表的 bug 非常依赖可视化肉眼看循环变量远不如打印直接。4.2 空链表和单节点链表很多代码在while (tail ! nullptr count k)里是安全的因为空链表时 head 为 nullptr最外层的 while 循环不会进入直接返回 dummy.next也是 nullptr。但如果代码开头没有判断head nullptr可能在别的地方先访问 head-next比如计算链表长度时那就很容易空指针崩溃。所以建议所有链表操作函数开头先处理空指针和 k 1 这类平凡情况。单节点链表和 k 的关系也值得注意。假设链表只有一个节点 1k 2那么尝试从 head 开始走两步时会发现走到第二步已经到 nullptrcount 只有 1小于 k最终原样返回。这是正确的。但如果写代码时不小心把 count 初始化为 1或者循环条件写成了count k就可能在只有一个节点时也强行翻转结果产生错误。边界条件里这种“差一”的错误很难通过肉眼发现最好配合单节点、双节点的小用例一起测。4.3 内存与指针悬挂问题链表反转题最大的坑就是指针丢失。翻转子链表时标准的循环是“先保存 next再修改当前节点的 next”。如果你先执行了cur-next prevNode再试图取cur-next保存到 nxt此时取到的已经不是原来的后继节点了链表就断了。这个顺序错误我见过很多人犯也包括最初的我。解决办法没有捷径只能在循环第一行就写 nxt 保存然后再动 cur-next。另一个容易被忽视的问题是递归版本中 head 指针的身份变化。在递归函数的参变量里head 最初是本组的头翻转完成后变成了本组的尾巴。如果你还把它当头用后续拼接就会出错。所以在递归版本的注释里一定要写清楚两句翻转前 head 是组头翻转后 head 是组尾。读到代码时心里要有一张状态图。内存管理方面如果你在某段代码里手动 new 了节点记得在不再需要时释放。但这类算法题通常只是操作已有节点不需要创建新节点所以一般不存在 delete 问题。如果是在工程链表里做翻转还要注意节点不能同时被两个不同的头引用否则可能出现 double free。用智能指针管理链表节点是更安全的做法但那是另一个话题了这里不过多展开。5. 变式与拓展面试官喜欢怎么升级这一类题目在面试里不会只考原题经常会被各种变式组合。但只要掌握了核心套路变式其实都是在三个环节上做文章分组方式、翻转条件、拼接规则。5.1 不足 k 个节点也要翻转原始题目的要求是“不足 k 个保持原顺序”但很多变式会反过来剩余节点数量不够 k 时也要把它们翻转。这个改动看起来很小实际处理方式却不同。递归版本非常简单只要删掉递归函数里的if (count k) return head;这一行当 cur 走到 nullptr 时表示后面没有完整一组了我们依然从 head 开始翻转整段剩余节点相当于把最后一组也翻过来。迭代版本则需要先遍历一次链表获得总长度算出完整组数然后只做那么多轮分组翻转最后一组剩余节点再单独调用一次普通反转。这个变式主要考察你有没有真正理解长度检查的意义——它只是在决定要不要提前终止而不是决定能不能翻转一个区间。5.2 从第 m 到第 n 个节点翻转另一个高频变式是反转从位置 m 到位置 n 的一段区间。思路和本题的一致只是不再按固定 k 划分而是手动指定边界。做法是先遍历找到第 m 个节点的前驱 pre再找到第 m 个节点 start 和第 n1 个节点 end然后翻转从 start 到 end 之前的区间翻转完了之后令pre-next newHead原来的 start现在变为段尾巴的 next 指向 end。你看这其实就是本题目中“单组翻转”的通用化。唯一要注意的是位置 m 可能是头节点此时 pre 为空所以仍然建议用虚拟头节点来处理统一逻辑。这类变式之所以很容易上手是因为你已经习惯了用“前驱节点 半开区间”来定义翻转范围。5.3 每 k 个一组翻转但每组之间再做点“花样”也有题目会在分组之外增加额外条件比如每 k 个一组翻转之后再把所有组之间的顺序反过来或者隔一组翻转一组又或者只对长度超过 k 的组翻转。这些题看起来五花八门本质上都是对分组边界和翻转动作的组合。我的建议是不要背答案而是掌握一个“步骤拆分”的思维模板第一步确定怎么分组第二步确定每组要不要翻转第三步确定组与组之间的连接方式。只要骨架清晰无论加什么花样都能往这三个赛道上套。另外说一个偏工程的扩展场景如果底层数据结构不是单链表而是双向链表翻转一个子段会稍微简单一些因为每个节点有 prev 和 next 两个指针你只需要把它们交换即可。但双向链表的分组翻转依然要非常注意头尾哨兵节点以及 NULL 边界。虽然这个题目通常不会考双向链表但理解了单向版本再去看双向版本会容易很多。6. 从这题我学会的一些通用套路6.1 链表题先画图再写代码我见过很多同学拿到链表题直接开写写完测不过就瞎改指针。这种方法效率极低。链表操作本身就是“指针迷宫”人的短期记忆处理不了三个以上指针同时变动的情况。所以我的习惯是在草稿纸上画一条长链表标出 prev、groupStart、tail、next 等指针在每一阶段的位置然后照着图写代码。这道题尤其适合这样因为迭代过程中有四个指针同时在动画完图代码基本就出来了。画图时不需要很精美只要箭头清晰能区分每个指针指到哪个节点就行。6.2 虚拟头节点的妙用虚拟头节点 dummy 的价值在于它让“头节点需要变化”的链表操作统一成普通情况。比如反转整条链表后原来的 head 会变成尾巴新的头是另一个节点。如果没有 dummy你在返回时需要判断是返回 head 还是返回新节点有了 dummy你只需要始终返回 dummy.next。本题中每翻转一组链表的头可能多次变化有了 dummy 就能轻松处理。这个技巧同样适用于删除倒数第 n 个节点、合并有序链表等题目。我用过一次之后就再也不想写没有 dummy 的链表修改逻辑了。6.3 用“半开区间”定义要翻转的区间写代码时把子链表定义成[start, end)而不是[start, end]最大的好处是 end 指针天然指向下一组的起点不需要额外维护前一个节点。在翻转循环里结束条件就是cur ! end边界非常清晰不容易出现 off-by-one 错误。这个方法是我从这道题里找到的最有价值的收获后来用在了很多区间链表操作里。如果你发现自己在链表题里总差一个节点多半是区间定义不够明确。建议以后在所有需要翻转子链表、删除中间段的题里都尝试用半开区间来组织指针。最后说一个我自己的小经验做链表题别怕多写几个临时指针。有人追求代码最精简但这道题精简版往往更难读懂、更难调试。我宁愿多声明 prev、tail、cur、nxt甚至把变量名起长一点也不愿意为省几行把指针复用得一塌糊涂。等你把功能跑通再谈优化代码风格也不迟。希望这篇博客能帮你把“每 k 个一组翻转”这个经典关卡顺利闯过去也让你在之后遇到其他链表问题时能多一份从容。

相关新闻

TCP TIME_WAIT 详解:产生机制、排查思路与内核参数调优实践

TCP TIME_WAIT 详解:产生机制、排查思路与内核参数调优实践

最近又收到一条凌晨三点的告警:某服务的连接失败率突然飙到 20%,登录后台看了下,ss -ant | grep TIME_WAIT | wc -l一刷就是 6 万多条。这种场景我遇到过不止一次,很多朋友第一反应就是“赶紧把tcp_tw_recycle打开”,其…

2026/10/19 13:47:31 阅读更多 →
开放式代码审查:从形式化检查到高效团队协作的实践指南

开放式代码审查:从形式化检查到高效团队协作的实践指南

团队里每天都在做Code Review,但真正把Review做出价值、让人愿意投入去做的团队,说实话不多。有人把审查当成合并代码前的一道关卡,有人把它当成挑刺大会,也有人干脆批量点一下"Approved"就算交差。直到我慢慢把一套更开…

2026/10/19 13:47:31 阅读更多 →
从增删改查到高效查询:MySQL性能优化实战指南

从增删改查到高效查询:MySQL性能优化实战指南

做了这么多年数据相关工作,我最大的感受是:MySQL 入门最典型的瓶颈真的不是语法记不住,而是“每条 SQL 单独拎出来都认识,组合到一起、数据量一上来,就卡成幻灯片”。这篇实战指南,就是想顺着从“增删改查”…

2026/10/19 13:47:31 阅读更多 →

最新新闻

VLAN间通信详解:单臂路由、三层交换机SVI与ACL配置实战

VLAN间通信详解:单臂路由、三层交换机SVI与ACL配置实战

1. 先搞清楚:VLAN为什么天生“老死不相往来”很多人刚接触网络时会有个直觉疑问:既然VLAN能把一台物理交换机切成好几台“虚拟交换机”,那为什么不同VLAN之间默认就是不通的?ping不通,ARP也学不到,数据包仿…

2026/10/19 14:28:19 阅读更多 →
本科毕业论文用这8个AI论文平台,从开题到定稿效率翻倍

本科毕业论文用这8个AI论文平台,从开题到定稿效率翻倍

说句实话,本科毕业论文这件事,绝大多数麻烦不是“研究有多深”,而是“流程有多散”。从确定题目、收集文献、整理综述,到搭出提纲、写满字数、反复降重、调整格式,任何一个环节卡住,都能把人逼到凌晨两点还…

2026/10/19 14:28:19 阅读更多 →
MS7210驱动开发实战:寄存器配置、时序验证与调试避坑指南

MS7210驱动开发实战:寄存器配置、时序验证与调试避坑指南

简介:ms7210是宏晶微电子推出的一款高清视频解码芯片,支持H.264、MPEG2、VC-1等主流编码及3D视频解码,常用于视频输入输出处理、音频控制、嵌入式驱动开发等场景。压缩包内共22个文件,以C源码和头文件为主体,覆盖驱动框…

2026/10/19 14:28:19 阅读更多 →
TensorFlow底层API手写神经网络:从GradientTape到训练循环实战

TensorFlow底层API手写神经网络:从GradientTape到训练循环实战

1. 为什么我劝你别急着调库,先手写一遍神经网络很多人第一次接触深度学习,路径都差不多:装好框架,复制一段官方示例,跑通MNIST,看到准确率往上跳,就觉得自己"会了"。可真到了要改结构…

2026/10/19 14:28:19 阅读更多 →
文本转3D:从语义描述到可交互三维模型的技术解剖

文本转3D:从语义描述到可交互三维模型的技术解剖

1. 这不是“AI画图”,而是一次三维语义空间的具象化实验“Google 文本转 3D 生成蝴蝶博物馆”——这个标题刚出现时,我第一反应是点开看是不是又一个带滤镜的宣传动图。结果在某实验室的内部演示视频里,看到输入“iridescent blue morpho but…

2026/10/19 14:28:19 阅读更多 →
行为多样性MoB:四足机器人地形泛化的新路径

行为多样性MoB:四足机器人地形泛化的新路径

读到 walk_these_ways 这个项目名的时候,我脑子里其实先跳出来的是那首老歌,但在机器人运动学习这个语境里,它讲的是一个特别现实的问题:怎么让四足机器人不只在某个特定地形上走得有模有样,而是换到碎石、草地、斜坡甚…

2026/10/19 14:27:07 阅读更多 →

日新闻

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

简介:本资源为电源技术方向的学术研究文档,聚焦介质阻挡放电型臭氧发生器电源的频率跟踪型PWM控制策略,面向电力电子、高压电源及臭氧应用领域的科研人员与工程技术人员。针对负载呈容性、等效电容随外加电压升高而增大、谐振频率随之漂移的难…

2026/10/19 0:00:47 阅读更多 →
Vibe Coding 遇上 TaoToken:把开发者思维圣殿的灵感流接入统一 Key 通道

Vibe Coding 遇上 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/19 0:00:47 阅读更多 →
HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

【免费下载链接】HundredCV-Chat 项目地址: https://ai.gitcode.com/hf_mirrors/Jax-dan/HundredCV-Chat 点击查看 免费下载 HundredCV-Chat 是一个由 100 位青年简历数据开发而来的中文多轮对话数据集,共包含 24,750 组日常闲聊对话和 4,871 个话题标签…

2026/10/19 0:00:47 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/19 10:02:04 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/19 1:30:52 阅读更多 →

月新闻

我发现了一个新思路:用 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/19 2:54:50 阅读更多 →
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/19 9:10:22 阅读更多 →
黑夜航拍船只数据集训练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/18 12:16:16 阅读更多 →