news 2026/3/7 12:33:41

链表专题(八):精细操作的巅峰——「K 个一组翻转链表」

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
链表专题(八):精细操作的巅峰——「K 个一组翻转链表」

场景想象:

你有一列很长的火车(链表),现在要把车厢按 每 K 节为一组 进行掉头。

  • 比如K=2[1, 2]掉头变成[2, 1][3, 4]掉头变成[4, 3]...

  • 关键规则:如果最后剩下的车厢不够 K 节(比如剩下个5),那就保持原样,不用掉头。

难点:

  1. 分组判断:你得先看看后面够不够 K 个,够了才翻,不够就不动。

  2. 断链与重连:翻转子链表后,原来的头变成了尾,原来的尾变成了头。你需要把它们和上一组的尾巴以及下一组的头正确地接起来。

力扣 25. K 个一组翻转链表

https://leetcode.cn/problems/reverse-nodes-in-k-group/

题目分析:

  • 输入:链表头head,整数k

  • 目标:每k个节点一组进行翻转。

  • 输出:修改后的链表头节点。

核心思维:虚拟头结点 + 模块化翻转

既然是重复操作,我们最好把“翻转一个子链表”这个动作封装成一个独立逻辑,或者直接在循环里复用标准的反转代码。

操作流程:

  1. Group Check:从当前位置开始向后数 K 个。如果数到了 null 还没够 K 个,说明不用翻了,直接结束。

  2. Cut & Reverse

    • 记录下这一组的开始节点start)和结束节点end)。

    • 暂时切断end.next,把[start, end]这段链表拿去反转

    • 反转后,end变成了新头,start变成了新尾。

  3. Connect

    • 上一组的尾巴pre)连到这一组的新头end)。

    • 这一组的新尾巴start)连到下一组的开头nextGroup)。

  4. Move:更新prestart(因为start已经是这组的尾巴了),准备下一轮。

代码实现 (JavaScript)

JavaScript

/** * Definition for singly-linked list. * function ListNode(val, next) { * this.val = (val===undefined ? 0 : val) * this.next = (next===undefined ? null : next) * } */ /** * @param {ListNode} head * @param {number} k * @return {ListNode} */ var reverseKGroup = function(head, k) { // 1. 虚拟头结点:因为头结点可能会变(第一组翻转后,原来的头就不是头了) const dummy = new ListNode(0, head); // pre 指向当前要处理的这组 K 个节点的前一个节点 // 初始指向 dummy let pre = dummy; let end = dummy; while (end.next !== null) { // --- 步骤一:看看剩余长度够不够 K 个 --- for (let i = 0; i < k && end !== null; i++) { end = end.next; } // 如果 end 是 null,说明不够 k 个了,直接跳出,保持原样 if (end === null) break; // --- 步骤二:准备翻转 --- // 记录关键节点 let start = pre.next; // 这一组的开头 (翻转后会变成尾) let nextGroup = end.next; // 下一组的开头 (先存起来) // 把这一组从链表中切断,方便独立翻转 end.next = null; // --- 步骤三:翻转当前组 --- // 这里直接调用我们在 LC 206 写过的反转函数 // 反转 start 到 end 这一段 pre.next = reverse(start); // --- 步骤四:重新连接 --- // 翻转后,start 变成了这一组的尾巴 // 把它连上下一组 start.next = nextGroup; // --- 步骤五:指针复位,准备下一轮 --- // pre 移动到这一组的尾巴 (也就是 start) pre = start; // end 也要复位到 pre,开始下一轮的计数 end = pre; } return dummy.next; }; // 辅助函数:标准的链表反转 (LC 206) // 输入一个头结点,返回反转后的新头结点 function reverse(head) { let pre = null; let cur = head; while (cur !== null) { let temp = cur.next; cur.next = pre; pre = cur; cur = temp; } return pre; }

深度模拟

假设1 -> 2 -> 3 -> 4 -> 5,k = 2

Round 1:

  • pre = dummy,end = dummy

  • end走 2 步 -> 指向2。够 K 个。

  • start = 1,nextGroup = 3

  • 切断:2.next = null。链表片段1 -> 2

  • 反转:变成2 -> 1

  • 连接

    • pre.next(dummy.next) 指向2

    • start.next(1.next) 指向3

    • 当前链表:dummy -> 2 -> 1 -> 3 -> 4 -> 5

  • 复位pre移到1end移到1

Round 2:

  • end走 2 步 -> 指向4。够 K 个。

  • start = 3,nextGroup = 5

  • 切断:4.next = null。片段3 -> 4

  • 反转:变成4 -> 3

  • 连接

    • pre.next(1.next) 指向4

    • start.next(3.next) 指向5

    • 当前链表:dummy -> 2 -> 1 -> 4 -> 3 -> 5

  • 复位pre移到3end移到3

Round 3:

  • end走 2 步... 哎呀,只有5一个了,不够 2 步。

  • break退出循环。

  • 最后剩下的5保持原样接在后面。

总结

这道题虽然难,但只要你引入了helper 函数 (reverse),主逻辑就会变得非常清晰。

  • 它是LC 206 (反转)的多次调用。

  • 它是Dummy Head的经典应用。

  • 它是指针断链与重连的集大成者。


下一题预告:LRU 缓存

拿下这个 Hard 之后,纯算法层面的链表题你已经通关了!🎉

最后一道压轴题 LC 146. LRU 缓存(专题九),我们不再是单纯地翻转指针,而是要设计一个数据结构。

  • 这是一个工程题,也是 Vue、React 源码里缓存机制的简化版。

  • 你需要结合HashMap双向链表,实现一个“最近最少使用”的淘汰算法,要求getput操作都是$O(1)$

准备好从“算法做题家”变身为“架构设计师”了吗?这可是前端面试的终极必考题

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/1 11:33:50

2026趋势:AI驱动性能优化

AI正重构性能测试的底层逻辑‌ 到2026年&#xff0c;AI已不再是软件测试中的“辅助工具”&#xff0c;而是‌性能优化的决策中枢‌。传统基于固定脚本、人工调参、静态基线的性能测试模式&#xff0c;正被‌自适应、可解释、低成本的AI驱动体系‌全面取代。测试工程师的角色&a…

作者头像 李华
网站建设 2026/3/4 21:56:10

CFD:针对离散计算部分用OpenMP多线程化,如何选择最优线程数

文章目录一、基本原则二、实用估计方法方法 1&#xff1a;基于经验公式&#xff08;适用于均匀网格&#xff09;方法 2&#xff1a;基于内存带宽瓶颈估计方法 3&#xff1a;运行时自适应调优&#xff08;推荐&#xff09;三、OpenMP 设置建议四、额外建议总结在 OpenMP 并行化基…

作者头像 李华
网站建设 2026/3/4 19:32:27

网络安全核心技术一网打尽:从常见攻防手段到风险防范的全景图

伴随着互联网的发展&#xff0c;它已经成为我们生活中不可或缺的存在&#xff0c;无论是个人还是企业&#xff0c;都离不开互联网。正因为互联网得到了重视&#xff0c;网络安全问题也随之加剧&#xff0c;给我们的信息安全造成严重威胁&#xff0c;而想要有效规避这些风险&…

作者头像 李华
网站建设 2026/3/2 17:47:46

收藏!AI工程师分2派?一文分清传统算法与大模型应用,小白转行必看

提到AI工程师&#xff0c;不少人第一反应就是“写代码、调模型的技术大牛”。但其实AI工程师圈子里藏着两大核心分支——传统算法工程师和AI大模型应用开发工程师。简单来说&#xff0c;前者负责“让模型变聪明”&#xff0c;后者专注“让聪明的模型落地能用”&#xff0c;两者…

作者头像 李华