LeetCode 25. K 个一组翻转链表 | 硬核拆解「reverse N」核心思路

LeetCode 25. K 个一组翻转链表 | 硬核拆解「reverse N」核心思路

✨ LeetCode 25. K 个一组翻转链表 | 硬核拆解「reverse N」核心思路

链表作为数据结构的基础考点,K 个一组翻转链表是进阶高频题型,它完美融合了「单组链表翻转」与「分段处理」的核心思想。本文将严格围绕reverse N 实现思路,从问题定义、算法原理、代码实现到调试踩坑,逐帧拆解这道经典题,带你彻底吃透链表分段翻转的底层逻辑!


视频地址

因为想更好的为大佬服务,制作了同步视频,这是Bilibili的视频地址

🔍 一、问题核心含义:K 个一组翻转链表

1. 官方定义(严格版)

k 个节点为一个分组,对链表的每一组进行完整反转;若链表剩余节点数量不足 k 个,则保持原有顺序不翻转

2. 直观示例

输入链表:1 -> 2 -> 3 -> 4 -> 5,k = 3

  • 第一组:1、2、3(满足 3 个节点)→ 翻转 → 3 -> 2 -> 1
  • 第二组:4、5(不足 3 个节点)→ 不翻转
  • 最终输出:3 -> 2 -> 1 -> 4 -> 5

3. 可视化流程图(Mermaid)

原链表: 1->2->3->4->5

分组 k=3

第一组: 1,2,3

第二组: 4,5

翻转后: 3->2->1

不翻转: 4->5

最终链表: 3->2->1->4->5

图表说明:清晰展示了「分组→判断长度→分组翻转→拼接结果」的全流程,不足 k 个的分组直接保留原序。


📊 二、算法原理:基于「reverse N」的分层实现

本题的核心解题思路是拆分法:将「K 组翻转」拆解为两个基础能力的组合——

  1. reverse N 计数判断:检查当前链表是否有足够的 N 个节点供翻转;
  2. __reverse N 私有翻转:真正实现「翻转链表前 N 个节点」的核心逻辑。

这是官方推荐的最优解思路,无冗余操作,时间复杂度趋近于 O(n)。

1. 基础能力:reverse N 节点计数判断

作用:前置校验,避免对不足 k 个节点的分组执行翻转。

实现逻辑:

  • 定义指针 p 指向当前分组的头节点;
  • 循环递减 k,同时让 p 向后遍历;
  • 若循环结束后 p 不为空 → 剩余节点 ≥k,可翻转;
  • p 为空 → 剩余节点 <k,终止翻转。

2. 核心能力:__reverse N 前 N 个节点翻转

这是真正执行翻转的私有函数,严格遵循题目指定逻辑:

  • 递归终止条件:n == 1,直接返回当前头节点(最后一个节点是新头);
  • 定义 tail:指向 head->next(原分组头节点,翻转后成为分组尾节点);
  • 定义 newHead:递归翻转后的新头节点;
  • 最终返回 newHead(翻转后分组的头节点)。

💡 三、整体实现框架:虚拟头节点 + 双指针循环

链表翻转的最大坑点是头节点会变化,因此必须使用虚拟头节点技巧破局;同时通过双指针记录关键位置,保证分组拼接不断裂。

1. 核心技巧:虚拟头节点

创建一个虚拟节点 dummy,让 dummy->next = 原链表头节点

作用:无论链表头节点如何翻转,最终直接返回 dummy->next 即可,彻底解决头节点边界问题

2. 关键位置指针定义

我们定义两个核心指针,这是循环翻转的关键:

指针名称核心作用位置变化
p待翻转区域的前驱节点始终指向当前分组的前一个节点,初始指向虚拟头
q待翻转区域的头节点 / 翻转后的尾节点初始 = p->next,翻转后成为当前分组的尾节点,是下一次的 p

3. 循环翻转逻辑

  1. reverseN(q, k) 为循环条件(返回非空说明可翻转);
  2. 执行翻转,将前驱节点 p 与新头节点拼接;
  3. 指针后移:p = q(当前分组尾 → 下一组前驱),q = p->next(下一组头);
  4. 直到 reverseN 返回空,循环结束。

⚠️ 四、C++ 关键代码实现

以下是精简核心版代码,仅保留性能关键逻辑,注释全覆盖核心步骤:

 #include <iostream> using namespace std; // 链表节点定义 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) {} }; class Solution { public: // ===================== 核心1:翻转前n个节点(__reverseN)===================== ListNode* __reverseN(ListNode* head, int n) { // 终止条件:n=1,返回当前头(翻转后新头) if (n == 1) return head; // tail:原分组头,翻转后是分组尾节点 ListNode* tail = head->next; // 递归翻转剩余n-1个节点 ListNode* newHead = __reverseN(head->next, n-1); // 拼接节点:尾节点指向当前头 tail->next = head; head->next = nullptr; return newHead; } // ===================== 核心2:判断是否有n个节点(reverseN判断)===================== ListNode* hasNNode(ListNode* head, int n) { ListNode* p = head; // 向后数n个节点 while (n-- && p) { p = p->next; } // p非空=有n个节点,返回p;空=不足n个,返回nullptr return p; } // ===================== 主函数:K个一组翻转 ===================== ListNode* reverseKGroup(ListNode* head, int k) { // 虚拟头节点(解决头节点翻转边界) ListNode* dummy = new ListNode(-1); dummy->next = head; // p:待翻转区前驱;q:待翻转区头节点 ListNode* p = dummy; ListNode* q = p->next; // 循环:有k个节点则翻转,否则终止 while (hasNNode(q, k)) { // 翻转q开头的k个节点,得到新头 ListNode* newHead = __reverseN(q, k); // 前驱节点拼接新头 p->next = newHead; // 指针后移:p=当前分组尾,q=下一组头 p = q; q = p->next; } // 返回最终链表头(虚拟头的next) return dummy->next; } }; 

🐛 五、调试实战:踩坑与修复(返回值核心问题)

在编写代码时,返回值错误是最常见的bug,结合题目要求复盘调试过程:

1. 初始错误

✅ 问题:最初直接返回 head(原链表头节点),导致结果错乱;

✅ 原因:分组翻转后,原链表头节点变成了第一组的尾节点,不再是整个链表的头。

2. 修复方案

返回虚拟头节点的nextreturn dummy->next,无论头节点如何翻转,虚拟头始终指向链表真正的头。

3. 翻转判断逻辑

题目指定关键判断:

if (p->next != q) → 说明发生了翻转;

if (p->next == q) → 说明未翻转(不足k个节点)。

该判断用于验证分组是否成功翻转,是调试的核心依据。


📈 六、复杂度分析

  1. 时间复杂度:O(n)

每个节点仅被遍历一次(计数一次 + 翻转一次),无嵌套循环;

  1. 空间复杂度:O(k)

递归调用栈深度为 k(分组长度),若改用迭代版 __reverseN,空间可优化为 O(1)。


✅ 七、总结与技巧提炼

  1. 核心思想:大问题拆小 → 用 reverseN 做计数校验,__reverseN 做单组翻转;
  2. 必用技巧:虚拟头节点解决链表头变化的边界问题;
  3. 指针关键p 记录前驱,q 记录分组头尾,保证链表不断裂;
  4. 终止条件:剩余节点不足 k 个时,直接终止循环,不做任何操作。
 LeetCode 25. K 个一组翻转链表 | 硬核拆解「reverse N」核心思路

这道题是链表递归+迭代的综合运用,吃透「reverse N」思路,所有链表分段翻转类题目都能迎刃而解!

Read more

【GitHub项目推荐--AI-Goofish-Monitor:闲鱼智能监控机器人完全指南】

简介 AI-Goofish-Monitor 是一个基于 Playwright 和 AI 技术的闲鱼(Goofish)多任务实时监控与智能分析工具。该项目由 dingyufei615 开发,通过先进的浏览器自动化技术和多模态大语言模型,为用户提供智能化的闲鱼商品监控解决方案。该工具不仅具备强大的数据采集能力,还配备了功能完善的 Web 管理界面,让用户能够轻松管理和配置监控任务。 🔗 GitHub地址 : https://github.com/dingyufei615/ai-goofish-monitor ⚡ 核心价值 : AI智能分析 · 多任务监控 · 实时通知 · Web管理界面 技术特色 : * AI驱动 :集成多模态大语言模型(GPT-4o、Gemini等),深度分析商品信息 * Web管理 :完整的可视化界面,无需命令行操作 * 多平台通知 :支持 ntfy.sh、企业微信、Bark 等多种通知方式 * 智能过滤 :基于自然语言的任务创建和AI分析标准生成 * 云原生支持 :提供

By Ne0inhk
ESP-Drone: 乐鑫 ESP32/ESP32-S2/ESP32-S3 开发的小型无人机解决方案

ESP-Drone: 乐鑫 ESP32/ESP32-S2/ESP32-S3 开发的小型无人机解决方案

目录 概述 1 主要特性 2 ESP-Drone无人机的硬件类型 3 硬件组装示意图 4 项目源代码 概述 ESP-Drone 是基于乐鑫 ESP32/ESP32-S2/ESP32-S3 开发的小型无人机解决方案,可使用手机 APP 或游戏手柄通过 Wi-Fi 网络进行连接和控制。该方案硬件结构简单,代码架构清晰,支持功能扩展,可用于 STEAM 教育等领域。 1 主要特性 ESP-Drone 具备以下特性: 支持自稳定模式 (Stabilize mode):自动控制机身水平,保持平稳飞行。支持定高模式 (Height-hold mode):自动控制油门输出,保持固定高度。支持定点模式 (Position-hold mode):自动控制机身角度,保持固定空间位置。支持 PC 上位机调试:

By Ne0inhk
AirSim无人机仿真入门(一):实现无人机的起飞与降落

AirSim无人机仿真入门(一):实现无人机的起飞与降落

概述: 安装好所需要的软件和环境,通过python代码控制无人机进行起飞和降落。 参考资料: 1、知乎宁子安大佬的AirSim教程(文字教程,方便复制) 2、B站瑜瑾玉大佬的30天RL无人机仿真教程(视频教程,方便理解) 3、AirSim官方手册(资料很全,不过是纯英文的) AirSim无人机仿真入门(一):实现无人机的起飞与降落 * 1 安装AirSim * 1.1 参考教程 * 1.2 内容梳理 * 1.3 步骤总结 * 2 开始使用 AirSim * 2.1 参考教程 * 2.2 内容梳理 * 2.3 步骤总结 * 3 撰写python控制程序 * 3.1 参考教程 * 3.2 内容梳理

By Ne0inhk
从0到1打造RISC-V智能家居中控:硬件+固件+通信全链路实战

从0到1打造RISC-V智能家居中控:硬件+固件+通信全链路实战

👋 大家好,欢迎来到我的技术博客! 📚 在这里,我会分享学习笔记、实战经验与技术思考,力求用简单的方式讲清楚复杂的问题。 🌱 无论你是刚入门的新手,还是正在进阶的开发者,希望你都能有所收获! 文章目录 * 从0到1打造RISC-V智能家居中控:硬件+固件+通信全链路实战 🏠💡 * 为什么选择RISC-V?🤔 * 系统整体架构概览 🧩 * 第一步:硬件选型与电路搭建 🔌 * 主控芯片选择 * 外设连接 * 第二步:开发环境搭建 🛠️ * 安装步骤(以Ubuntu为例) * 第三步:裸机驱动开发(Bare Metal)⚡ * 示例1:DHT11温湿度读取(Bit-banging) * 示例2:BH1750光照传感器(I2C) * 第四步:引入FreeRTOS实现多任务调度 🔄 * 第五步:Wi-Fi连接与MQTT通信 ☁️📡 * 连接Wi-Fi * MQTT客户端(使用esp-mqtt库) * 第六步:BLE本地控制(无需Wi-Fi)📱

By Ne0inhk